有一个文件: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

我需要能够在每个名称之后将行中的$ 2数据生成到列中。 (主机)和csv类型格式,标题可选。我不能使用(,:)作为分隔符,因为数据包含它们(tab或;)。
像:
name;displayName;capacityInKB;consumedCapacityInKB;dpPoolID
devtwr1;00:67:BB;104,857,600;4,042,752;20
;00:7B:FD;52,428,800;14,880,768;10
;00:7C:28;34,179,712;29,804,544;20
;00:7C:29;34,179,712;5,462,016;20
devtwr2;00:67:BB;104,857,600;4,042,752;20
;00:7B:FD;52,428,800;14,880,768;10
;00:7C:28;34,179,712;29,804,544;20
;00:7C:29;34,179,712;5,462,016;20

希望有人可以提供帮助。
答案 0 :(得分:0)
我相信这可以做你想要的:
$ awk '$1=="name"{name=$2} $1 ~/^(displayName|capacityInKB|consumedCapacityInKB)$/{out=out";"$2} $1=="dpPoolID"{print name out";"$2; name=" "; out=""}' Ntab.txt
devtwr1;00:67:BB;104,857,600;4,042,752;20
;00:7B:FD;52,428,800;14,880,768;10
;00:7C:28;34,179,712;29,804,544;20
;00:7C:29;34,179,712;5,462,016;20
devtwr2;00:67:BB;104,857,600;4,042,752;20
;00:7B:FD;52,428,800;14,880,768;10
;00:7C:28;34,179,712;29,804,544;20
;00:7C:29;34,179,712;5,462,016;20
awk
一次读取每一行。每行分为几个字段。第一个字段称为$1
,第二个字段称为$2
。
$1=="name"{name=$2}
这会捕获变量name
中的名称。
$1~/^(displayName|capacityInKB|consumedCapacityInKB)$/{out=out";"$2}
当我们遇到displayName
,capacityInKB
或consumedCapacityInKB
的任何行时,请将其值附加到变量out
。
$1=="dpPoolID"{print name out";"$2; name=" "; out=""}
当我们到达dpPoolID
的行时,打印出收集的值。重置out
以清空并将name
设置为空格。
作为替代输出格式,我们可以保留名称并在每行显示:
$ awk '$1=="name"{name=$2} $1 ~/^(displayName|capacityInKB|consumedCapacityInKB)$/{out=out";"$2} $1=="dpPoolID"{print name out";"$2; out=""}' Ntab.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
答案 1 :(得分:0)
您要求awk
,如果适合您,则应接受John1024的解决方案。但这就是我想要用Perl来解决的问题。这是该语言的一种解决方案。它有一个小优势(IMO),因为它不依赖于每个记录中字段的特定顺序,除了displayName
表示新集合的开始。
$ 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};
}' ntab.txt
输出:
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
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