Добавить null в столбцы, которые пусты

Я пытаюсь поместить нуль в столбцы, которые пусты, используя perl или awk, чтобы найти номер столбца, можно использовать количество столбцов заголовка. Я попытался выполнить решение, используя perl и некоторое регулярное выражение. Однако вывод выглядит очень близко к желаемому выводу, но если внимательно присмотреться, в строке номер один отображаются неверные данные.

Входные данные:

id      name           type          foo-id  zoo-id  loo-id-1  moo-id-2
-----  ---------------  -----------  ------  ------  ------  ------
0      zoo123        soozoo          8               31        32
51     zoo213        soozoo          48      51
52     asz123        soozoo          47      52
53     asw122        soozoo          1003    53
54     fff123        soozoo          68      54
55     sss123        soozoo          75      55
56     ssd123        soozoo          76      56

Ожидаемый результат:

0      zoo123        soozoo          8       null      31        32
51     zoo213        soozoo          48      51        null      null
52     asz123        soozoo          47      52        null      null
53     asw122        soozoo          1003    53        null      null
54     fff123        soozoo          68      54        null      null
55     sss123        soozoo          75      55        null      null
56     ssd123        soozoo          76      56        null      null

Очень близко к решению, но строка 1 показывает неверные данные:

echo "$x"|grep -E '^[0-9]+'  |perl -ne 'm/^([\d]+)(?:\s+([\w]+))?(?:\s+([-\w]+))?(?:\s+([\d]+))?(?:\s+([\d]+))?(?:\s+([\d]+))?(?:\s+([\d]+))?/;printf "%s %s %s %s %s %s %s\n", $1, $2//"null", $3//"null",$4//"null",$5//"null",$6//"null",$7//"null"' |column -t
0   zoo123  soozoo  8     31  32    null
51  zoo213  soozoo  48    51  null  null
52  asz123  soozoo  47    52  null  null
53  asw122  soozoo  1003  53  null  null
54  fff123  soozoo  68    54  null  null
55  sss123  soozoo  75    55  null  null
56  ssd123  soozoo  76    56  null  null

Вам нужно будет разделить данные по номерам столбцов, потому что между столбцами нет разделителя, и любой нулевой столбец, не входящий в конечные столбцы, будет неправильно истолкован. Это довольно болезненно. С GNU cut вы можете использовать cut --output-delimiter='|' -c 1-7,8-21,22-37,38-45,46-53,54-63,64- для получения полей вывода, разделенных вертикальной чертой. Тогда обнаружить пустые поля и заменить данные на null довольно просто.

Jonathan Leffler 23.12.2020 05:47

Ваши подчеркивания в строке 2 действительно не совпадают с заголовками в строке 1?

jhnc 23.12.2020 06:17
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
90
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

С ГНУ awk:

awk 'NR>2{                     # ignore first and second row
       NF=7                    # fix number of columns
       for(i=1; i<=NF; i++)    # loop with all columns
         if ($i ~ /^ *$/){      # if empty or only spaces
           $i = "null"
         }
       print $0}' FIELDWIDTHS='7 14 16 8 8 10 8' OFS='|' file | column -s '|' -t

Как одна строка:

awk 'NR>2{NF=7; for(i=1;i<=NF;i++) if ($i ~ /^ *$/){$i = "null"} print $0}' FIELDWIDTHS='7 14 16 8 8 10 8' OFS='|'  file | column -s '|' -t

Выход:

0        zoo123          soozoo            8         null  31          32
51       zoo213          soozoo            48        51    null        null
52       asz123          soozoo            47        52    null        null
53       asw122          soozoo            1003      53    null        null
54       fff123          soozoo            68        54    null        null
55       sss123          soozoo            75        55    null        null
56       ssd123          soozoo            76        56    null        null

См.: 8 мощных встроенных переменных Awk — FS, OFS, RS, ORS, NR, NF, FILENAME, FNR

Разве это не относится к gawk/не-posix? Кроме того, вы можете установить FIELDWIDTHS динамически из первой или второй строки (если это надежно)

jhnc 23.12.2020 06:25
Ответ принят как подходящий

Когда у вас есть строка фиксированной ширины для анализа, вы обнаружите, что unpack() — лучший инструмент, чем регулярные выражения.

Это должно продемонстрировать, как это сделать. Я оставлю это вам, чтобы преобразовать его в однострочник.

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

while (<DATA>) {
  next if /^\D/; # Skip lines that don't start with a digit

  # I worked out the unpack() template by counting columns.
  my @data = map { /\S/ ? $_ : 'null' } unpack('A7A14A16A8A8A8A8');

  say join ' ', @data;
}

__DATA__
id      name           type          foo-id  zoo-id  loo-id-1  moo-id-2
-----  ---------------  -----------  ------  ------  ------  ------
0      zoo123        soozoo          8               31        32
51     zoo213        soozoo          48      51
52     asz123        soozoo          47      52
53     asw122        soozoo          1003    53
54     fff123        soozoo          68      54
55     sss123        soozoo          75      55
56     ssd123        soozoo          76      56

Выход:

$ perl unpack | column -t
0   zoo123  soozoo  8     null  31    32
51  zoo213  soozoo  48    51    null  null
52  asz123  soozoo  47    52    null  null
53  asw122  soozoo  1003  53    null  null
54  fff123  soozoo  68    54    null  null
55  sss123  soozoo  75    55    null  null
56  ssd123  soozoo  76    56    null  null

подскажите пожалуйста как вы рассчитали 'A7A14A16A8A8A8A8' или простой ресурс почитать ? официальный документ мне трудно понять. Спасибо.

monk 23.12.2020 16:12

@monk: Раздел о строках в perlpacktut был бы хорошим местом для начала. Но это «A» (что означает обработку данных как строки), за которым следует число, представляющее собой ширину столбца (которое я получил, просто подсчитав символы во входных данных).

Dave Cross 23.12.2020 17:03

Другие вопросы по теме