我有一个以下格式的文件。
abc|xyz|mno
x up x
up up x
x x up
abc|xyz|mno
x x x
up x x
....
....
基本上,文件的第一行是设备名称(|ed)
,接下来的行是设备的状态。
我希望输出采用以下格式:
abc,x|xyz,up|mno,x
abc,up|xyz,up|mno,x
abc,x|xyz,x|mno,up
abc,x|xyz,x|mno,x
abc,up|xyz,x|mno,x
....
....
你有什么指点吗?
答案1
如果您可以将perl
, 与List::MoreUtils
CPAN 中的模块一起使用:
$ perl -MList::MoreUtils=pairwise -F'\|' -anle '
print and next if /^$/;
@dev = @F and next if @F > 1;
print join "|", pairwise {"$a,$b"} @dev,@{[split]};
' file
abc,x|xyz,up|mno,x
abc,up|xyz,up|mno,x
abc,x|xyz,x|mno,up
abc,x|xyz,x|mno,x
abc,up|xyz,x|mno,x
如果您不喜欢使用外部模块:
$ perl -F'\|' -anle '
print and next if /^$/;
@dev = @F and next if @F > 1;
@state = split;
print join "|", map {"$dev[$_],$state[$_]"} 0..$#dev;
' file
答案2
awk
如果输入与描述完全相同,以下命令应该执行您想要的操作(但它不执行任何错误检查):
awk '/\|/ {split($0, devices, "|"); next} /^$/ {print; next}
{for (i=1; i<NF; i++) printf "%s,%s|", devices[i], $i; printf "%s,%s\n", devices[NF], $NF}'
- 如果输入行包含 a
|
,则在|
s 处将其拆分为一个名为“devices”的数组。 (我们需要使用,\|
因为普通|
意味着或者,如/cat|dog/
。)然后继续执行next
输入数据行(即,不执行以下命令)。 - 如果输入行为空,则打印它(空行)并继续到下一行,而不执行以下命令。
- 对于与上述之一不匹配的每一行,对于每个字段最多但不包括最后,打印相应的设备名称和换行符,
|
但不包含换行符。然后用换行符打印最后一个字段,但不打印|
。