我有以下数据(它还包含其他行,这里是一个有意义的摘录):
group
bb 1
cc 1
dd 1
end
group
dd 2
bb 2
end
group
aa 3
end
我不知道值(如"1", "2",等等),必须匹配的名称(通用"组", ";我想得到的数据过滤和排序按以下顺序(与空制表符时,字符串不存在):
group bb 1 cc 1 dd 1
group bb 2 dd 2
group aa 3
我运行:
awk 'BEGIN {ORS = "t"}
/^group/ {print "n" $0};
/^aa/ {AA = $0};
/^bb/ {BB = $0};
/^cc/ {CC = $0};
/^dd/ {DD = $0};
/^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**
的顺序是正确的,但是数据是错误的(用星号标记)。做这种过滤的正确方法是什么?谢谢!
假设:
- 输入行不以空格开头
- 每个
^group
有一个匹配的^end
- 文件的第一行是
^group
- 文件的最后一行是
^end
^end
和下一个^group
之间没有行(可以忽略)
主要问题是,每次看到group
时,我们都需要清除/重置其他变量,否则我们会延续之前group
的值。
其他(次要)问题:
ORS
vsOFS
- 多个
print
命令vs单个print
命令 - 不需要行延续字符(
)
更新awk
脚本的一个想法:
awk '
BEGIN { OFS="t" }
/^group/ { AA=BB=CC=DD="" ; next }
/^aa/ { AA=$0 ; next }
/^bb/ { BB=$0 ; next }
/^cc/ { CC=$0 ; next }
/^dd/ { DD=$0 ; 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[$1]=$0} /^end$/{
printf "groupt%st%st%st%sn", m["aa"], m["bb"], m["cc"], m["dd"]
}' file
group bb 1 cc 1 dd 1
group bb 2 dd 2
group aa 3
使用GNUawk
尝试以下代码。书面和测试仅显示样品。简单的解释是,将RS设置为endn(可选),然后简单地用空格替换新行并打印该行。
awk -v RS='endn?' 'RT{gsub(/n/,OFS);print}' Input_file
或如果您想要以制表符分隔输出,请尝试以下操作:
awk -v RS='endn?' -v OFS="t" 'RT{gsub(/n/,OFS);print}' Input_file