如何使用 awk 将 mixed/partly 缺失的记录提取到定义的顺序

How to extract mixed/partly absent records to a defined order with awk

我有以下数据(它还包含其他行,这里是一个有意义的摘录):

group
bb 1
cc 1
dd 1
end
group
dd 2
bb 2
end
group
aa 3
end

我不知道值(如“1”、“2”等),必须通过名称(通用“group”、“aa”等)进行匹配 我想按以下顺序过滤和排序数据(当字符串不存在时使用空选项卡):

group       bb 1    cc 1    dd 1
group       bb 2            dd 2
group   aa 3            

我运行:

awk 'BEGIN {ORS = "\t"}\
/^group/ {print "\n" [=13=]}; \
/^aa/ {AA = [=13=]}; \
/^bb/ {BB = [=13=]}; \
/^cc/ {CC = [=13=]}; \
/^dd/ {DD = [=13=]}; \
/^end/ {print AA; print BB; print CC; print DD}' test.txt

并得到

group       bb 1    cc 1    dd 1
group       bb 2    **cc 1**    dd 2
group   aa 3    **bb 2**    **cc 1**    **dd 2**

顺序正确,但数据错误(标有星号)。执行此过滤的正确方法是什么? 谢谢!

假设:

  • 输入行不以任何白色开头space
  • 每个 ^group 都有匹配的 ^end
  • 文件的第一行是^group
  • 文件的最后一行是 ^end
  • ^end 和下一个 ^group
  • 之间没有行(忽略)

主要问题是每次看到 group 时,我们都需要 clear/reset 其他变量,否则我们会沿用之前 group.

的值

其他(次要)问题:

  • ORS 对比 OFS
  • 多个print命令与单个print命令
  • 不需要续行符(\)

更新 awk 脚本的一个想法:

awk '
BEGIN    { OFS="\t" }
/^group/ { AA=BB=CC=DD="" ; next }
/^aa/    { AA=[=10=]          ; next }
/^bb/    { BB=[=10=]          ; next }
/^cc/    { CC=[=10=]          ; next }
/^dd/    { DD=[=10=]          ; next }
/^end/   { print "group",AA,BB,CC,DD }
' test.txt

注意: ; next 子句是可选的,作为视觉提醒我们不需要担心脚本的其余部分(对于当前行)

这会生成:

group           bb 1    cc 1    dd 1
group           bb 2            dd 2
group   aa 3

这里有一个更简单的 awk 解决方案来做同样的事情:

awk '/^group$/{delete m; next} {m[]=[=10=]} /^end$/{
 printf "group\t%s\t%s\t%s\t%s\n", m["aa"], m["bb"], m["cc"], m["dd"]
}' file

group         bb 1   cc 1   dd 1
group         bb 2          dd 2
group   aa 3

使用 GNU awk 尝试以下代码。仅使用显示的示例编写和测试。简单的解释是,将 RS 设置为 end\n(可选),然后简单地用空格替换新行并打印该行。

awk -v RS='end\n?' 'RT{gsub(/\n/,OFS);print}' Input_file

OR 如果您想将输出作为制表符分隔,请尝试以下操作:

awk -v RS='end\n?' -v OFS="\t" 'RT{gsub(/\n/,OFS);print}' Input_file