我有一个数据列表,格式如下:
Joined : a
Whatever : b
Last visited : c
Useful : y
NotUseful1 : f
Email : z
RandomWat : g
*** end ***
Joined : a
Whatever : b
Last visited : c
Useful : y
NotUseful1 : f
Email : z
RandomWat : g
*** end ***
Joined : h
Whatever : i
Last visited : j
Useful : k
NotUseful1 : l
Email : m
RandomWat : n
我想要的是:
Useful, Email, Joined, Last Visited
y,z,a,c
y,z,a,c
k,m,h,j
我可能喝了太多啤酒,但我不知道如何在固定长度的列中跨行获取值。实际上是一些特定输出的 CSV 格式。
我真的在寻找 sed/awk 中的东西,尽管任何文本处理器都可以。
最佳答案
您可以将 Awk 的记录分隔符设置为 **end**
并通过一些简单的解析来分离字段;但如果格式是一个完全稳定的系列,由固定顺序的八行组成,那么您真正需要的只是
awk -F ' *: *' -v OFS=, '{i=NR%8; a[i]=$NF }
i==7 { print a[4], a[7], a[1], a[3] }' file
如果您的值可能包含冒号,您将需要进行调整——这个简单的代码只是提取最后一个冒号之后的内容。
添加 CSV header 作为练习(或不添加)。
-F
选项设置输入字段分隔符,因此 Awk 将在冒号处拆分行,修剪任何相邻的空格。 OFS
是输出字段分隔符;我们希望输出以逗号分隔。 NR
为当前输入行号,%8
计算取模;所以 i
的值从 1 变为 7,然后回到零,然后再次开始攀升,在整个文件中重复。现在,我们使用 i
作为数组 a
的索引,并将每一行的最后一个字段收集到该数组中。当我们到达索引 7 时,我们拥有所需的所有字段,因此我们打印它们。 (我最初将其设置为 0,但那样会丢失最后一条记录,因为您的示例数据中没有终止 **end**
。)
NF
是输入字段的数量,我们希望它基本上始终为 2,所以我也可以在那里硬编码 $2
。如果您需要扩展它,我会完全忘记 -F ' *: *'
并手动 sub("^[^:]*: *", "")
然后将整个值放入 $0
。
关于bash - sed/awk 将成对的行合并为一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34780170/