awk 或 Perl 修改数据
awk or Perl to modify data
使用下面的 awk 和 Perl 解决方案:我需要了解如何添加不重复其输出的附加字段,就像这些示例中的 "name" 一样。
即 devtwr1 在示例数据中只出现一次,如果我需要添加也只出现一次的其他字段,这是如何完成的?
抱歉,已广泛尝试但无法解决...
这是来源:
有一个文件:Ntab.txt是两台主机的示例文件,真实文件中有无数台主机一个接一个。
每个主机有多个 "displayName"s(地址),每个 'displayName'.
都有相应的数字
>cat Ntab.txt
name devtwr1
displayName 00:67:BB
capacityInKB 104,857,600
consumedCapacityInKB 4,042,752
dpPoolID 20
displayName 00:7B:FD
capacityInKB 52,428,800
consumedCapacityInKB 14,880,768
dpPoolID 10
displayName 00:7C:28
capacityInKB 34,179,712
consumedCapacityInKB 29,804,544
dpPoolID 20
displayName 00:7C:29
capacityInKB 34,179,712
consumedCapacityInKB 5,462,016
dpPoolID 20
name devtwr2
displayName 00:67:BB
capacityInKB 104,857,600
consumedCapacityInKB 4,042,752
dpPoolID 20
displayName 00:7B:FD
capacityInKB 52,428,800
consumedCapacityInKB 14,880,768
dpPoolID 10
displayName 00:7C:28
capacityInKB 34,179,712
consumedCapacityInKB 29,804,544
dpPoolID 20
displayName 00:7C:29
capacityInKB 34,179,712
consumedCapacityInKB 5,462,016
dpPoolID 20
我需要能够在每个 'name'(主机)之后将行中的 $2 数据生成为列,并且采用 csv 类型格式,标题可选。我不能使用 (,:) 作为分隔符,因为数据包含它们(制表符或 ;)。
喜欢:
name;displayName;capacityInKB;consumedCapacityInKB;dpPoolID
devtwr1;00:67:BB;104,857,600;4,042,752;20
devtwr1;00:7B:FD;52,428,800;14,880,768;10
devtwr1;00:7C:28;34,179,712;29,804,544;20
devtwr1;00:7C:29;34,179,712;5,462,016;20
devtwr2;00:67:BB;104,857,600;4,042,752;20
devtwr1;00:7B:FD;52,428,800;14,880,768;10
devtwr1;00:7C:28;34,179,712;29,804,544;20
devtwr1;00:7C:29;34,179,712;5,462,016;20
这是一个 Awk 解决方案,但无法解决如何添加 "name" 等并非所有字段都有数据的附加字段。
$ awk '=="name"{name=}
~/^(displayName|capacityInKB|consumedCapacityInKB)$/{out=out";"}
=="dpPoolID"{print name out";"; out=""}' tmp2.txt
devtwr1;00:67:BB;104,857,600;4,042,752;20
devtwr1;00:7B:FD;52,428,800;14,880,768;10
devtwr1;00:7C:28;34,179,712;29,804,544;20
devtwr1;00:7C:29;34,179,712;5,462,016;20
devtwr2;00:67:BB;104,857,600;4,042,752;20
devtwr2;00:7B:FD;52,428,800;14,880,768;10
devtwr2;00:7C:28;34,179,712;29,804,544;20
devtwr2;00:7C:29;34,179,712;5,462,016;20
这是一个 Perl 解决方案,但又一次无法解决如何添加其他字段的问题,例如 "name" 并不总是有数据的字段。
perl -lane '
BEGIN {
@fields = qw(name displayName capacityInKB consumedCapacityInKB dpPoolID);
print join ";", @fields;
}
if (/^(name|displayName)/ && $data{displayName}) {
print join ";", @data{@fields};
%data = ( name => $data{name} );
}
$data{$F[0]} = $F[1];
END {
print join ";",@data{@fields};
}' tmp2.txt > Report.csv
希望提供足够的信息以加深理解。
提前致谢。
将此保存到 ntab.pl 文件,执行 chmod +x ntab.pl 和 运行 it: cat ntab.txt | ./ntab.pl
#!/usr/bin/perl
use strict;
use constant CSV_SEP=>';';
my ($name,%flds);
my @fl=qw(displayName capacityInKB consumedCapacityInKB dpPoolID);
sub csv4name {
my ($name,$vals)=@_;
return 0 unless $name and %$vals;
print join("\n",map { my $i=$_; join(CSV_SEP,$name,map { $vals->{$_}[$i]||='' } @fl) } 0..$#{$vals->{'displayName'}})."\n";
}
while (my ($attr,$val)=split /\s+/,<>) {
if ($attr eq 'name') {
csv4name($name,\%flds);
$name=$val;
%flds=();
next;
}
push $flds{$attr}||=[],$val;
}
csv4name($name,\%flds);
没有任何性能优化,但对于不是非常大的文件 (<3G),此脚本可以顺利运行。
使用下面的 awk 和 Perl 解决方案:我需要了解如何添加不重复其输出的附加字段,就像这些示例中的 "name" 一样。 即 devtwr1 在示例数据中只出现一次,如果我需要添加也只出现一次的其他字段,这是如何完成的? 抱歉,已广泛尝试但无法解决...
这是来源:
有一个文件:Ntab.txt是两台主机的示例文件,真实文件中有无数台主机一个接一个。
每个主机有多个 "displayName"s(地址),每个 'displayName'.
都有相应的数字>cat Ntab.txt
name devtwr1
displayName 00:67:BB
capacityInKB 104,857,600
consumedCapacityInKB 4,042,752
dpPoolID 20
displayName 00:7B:FD
capacityInKB 52,428,800
consumedCapacityInKB 14,880,768
dpPoolID 10
displayName 00:7C:28
capacityInKB 34,179,712
consumedCapacityInKB 29,804,544
dpPoolID 20
displayName 00:7C:29
capacityInKB 34,179,712
consumedCapacityInKB 5,462,016
dpPoolID 20
name devtwr2
displayName 00:67:BB
capacityInKB 104,857,600
consumedCapacityInKB 4,042,752
dpPoolID 20
displayName 00:7B:FD
capacityInKB 52,428,800
consumedCapacityInKB 14,880,768
dpPoolID 10
displayName 00:7C:28
capacityInKB 34,179,712
consumedCapacityInKB 29,804,544
dpPoolID 20
displayName 00:7C:29
capacityInKB 34,179,712
consumedCapacityInKB 5,462,016
dpPoolID 20
我需要能够在每个 'name'(主机)之后将行中的 $2 数据生成为列,并且采用 csv 类型格式,标题可选。我不能使用 (,:) 作为分隔符,因为数据包含它们(制表符或 ;)。
喜欢:
name;displayName;capacityInKB;consumedCapacityInKB;dpPoolID
devtwr1;00:67:BB;104,857,600;4,042,752;20
devtwr1;00:7B:FD;52,428,800;14,880,768;10
devtwr1;00:7C:28;34,179,712;29,804,544;20
devtwr1;00:7C:29;34,179,712;5,462,016;20
devtwr2;00:67:BB;104,857,600;4,042,752;20
devtwr1;00:7B:FD;52,428,800;14,880,768;10
devtwr1;00:7C:28;34,179,712;29,804,544;20
devtwr1;00:7C:29;34,179,712;5,462,016;20
这是一个 Awk 解决方案,但无法解决如何添加 "name" 等并非所有字段都有数据的附加字段。
$ awk '=="name"{name=}
~/^(displayName|capacityInKB|consumedCapacityInKB)$/{out=out";"}
=="dpPoolID"{print name out";"; out=""}' tmp2.txt
devtwr1;00:67:BB;104,857,600;4,042,752;20
devtwr1;00:7B:FD;52,428,800;14,880,768;10
devtwr1;00:7C:28;34,179,712;29,804,544;20
devtwr1;00:7C:29;34,179,712;5,462,016;20
devtwr2;00:67:BB;104,857,600;4,042,752;20
devtwr2;00:7B:FD;52,428,800;14,880,768;10
devtwr2;00:7C:28;34,179,712;29,804,544;20
devtwr2;00:7C:29;34,179,712;5,462,016;20
这是一个 Perl 解决方案,但又一次无法解决如何添加其他字段的问题,例如 "name" 并不总是有数据的字段。
perl -lane '
BEGIN {
@fields = qw(name displayName capacityInKB consumedCapacityInKB dpPoolID);
print join ";", @fields;
}
if (/^(name|displayName)/ && $data{displayName}) {
print join ";", @data{@fields};
%data = ( name => $data{name} );
}
$data{$F[0]} = $F[1];
END {
print join ";",@data{@fields};
}' tmp2.txt > Report.csv
希望提供足够的信息以加深理解。 提前致谢。
将此保存到 ntab.pl 文件,执行 chmod +x ntab.pl 和 运行 it: cat ntab.txt | ./ntab.pl
#!/usr/bin/perl
use strict;
use constant CSV_SEP=>';';
my ($name,%flds);
my @fl=qw(displayName capacityInKB consumedCapacityInKB dpPoolID);
sub csv4name {
my ($name,$vals)=@_;
return 0 unless $name and %$vals;
print join("\n",map { my $i=$_; join(CSV_SEP,$name,map { $vals->{$_}[$i]||='' } @fl) } 0..$#{$vals->{'displayName'}})."\n";
}
while (my ($attr,$val)=split /\s+/,<>) {
if ($attr eq 'name') {
csv4name($name,\%flds);
$name=$val;
%flds=();
next;
}
push $flds{$attr}||=[],$val;
}
csv4name($name,\%flds);
没有任何性能优化,但对于不是非常大的文件 (<3G),此脚本可以顺利运行。