Perl 为空的列添加null
我试图使用Perl 为空的列添加null,perl,awk,Perl,Awk,我试图使用perl或awk将空列设置为null,以查找列数,可以使用标题的列计数。我尝试使用perl和一些正则表达式来执行解决方案。但是,输出看起来非常接近所需的输出,但是如果仔细注意,第一行显示的数据不正确 输入数据: id name type foo-id zoo-id loo-id-1 moo-id-2 ----- --------------- ----------- ------ ------ ------ ------
perl
或awk
将空列设置为null,以查找列数,可以使用标题的列计数。我尝试使用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
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#固定列数
对于(i=1;i2{NF=7;对于(i=1;i当您要解析一个固定宽度的字符串时,您会发现这是一个比正则表达式更好的工具
这应该演示如何做。我将让您将其转换为一行程序
#!/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
您需要按列号拆分数据,因为列之间没有分隔符,任何不在尾随列中的空列都会被误解。这非常痛苦。使用GNUcut
,您可以使用cut--output delimiter=''|'-c1-7,8-21,22-37,38-45,46-53,54-63,64-
来获取管道分隔的输出字段。然后找出空字段并用null
替换数据相当容易。第2行的下划线真的与第1行的标题不对齐吗?这不是针对gawk
/non-posix吗?此外,您可以从第一行或第二行动态设置字段宽度(如果可靠的话)谢谢。太神奇了!你能告诉我你是如何计算的'a7a14a16a8a8a8a8a8'
或者一个简单的资源来阅读吗?官方文件对我来说很难理解。谢谢。@monk:中关于字符串的部分是一个很好的开始。但是它是'a'(意思是将数据当作字符串处理)后跟一个数字,该数字是列的宽度(我通过计算输入数据中的字符数得到)。
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
#!/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