Я пытаюсь поместить нуль в столбцы, которые пусты, используя 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
Ваши подчеркивания в строке 2 действительно не совпадают с заголовками в строке 1?
С ГНУ 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
динамически из первой или второй строки (если это надежно)
Когда у вас есть строка фиксированной ширины для анализа, вы обнаружите, что 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: Раздел о строках в perlpacktut был бы хорошим местом для начала. Но это «A» (что означает обработку данных как строки), за которым следует число, представляющее собой ширину столбца (которое я получил, просто подсчитав символы во входных данных).
Вам нужно будет разделить данные по номерам столбцов, потому что между столбцами нет разделителя, и любой нулевой столбец, не входящий в конечные столбцы, будет неправильно истолкован. Это довольно болезненно. С GNU
cut
вы можете использоватьcut --output-delimiter='|' -c 1-7,8-21,22-37,38-45,46-53,54-63,64-
для получения полей вывода, разделенных вертикальной чертой. Тогда обнаружить пустые поля и заменить данные наnull
довольно просто.