bash - sed/awk 将成对的行合并为一行

标签 bash unix awk sed

我有一个数据列表,格式如下:

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/

相关文章:

bash - unix 排序,带主键和辅助键

UNIX 域套接字与共享内存(映射文件)

bash - 直接给pbs脚本传参

bash - 关于 FIFO 和文件描述符的问题

linux - 如何以另一个用户的身份使用 sudo 在 bash 子shell 中执行一系列命令?

arrays - 将数组值与用户输入的 bash 进行比较

shell - 如何在 Unix 命令行或 shell 脚本中打乱文本文件的行?

json - 使用 jq 和 awk 拆分大型 JSON 文件

sorting - 如何使用 awk 按长度对行进行排序?

regex - 如何从 Bash 中的字符串中删除重复字符?