使用 awk/sed/bash 检索所有必填字段后打印
Posted
技术标签:
【中文标题】使用 awk/sed/bash 检索所有必填字段后打印【英文标题】:printing after retrieving all the required fields using awk/sed/bash 【发布时间】:2019-04-04 02:26:57 【问题描述】:寻找使用 awk/sed/bash 以所需格式打印的正确方法。
考虑一个包含以下内容的文件 (awk_test.txt
),
Checkpoint number: ckpt.123
value1: 10
value2: 10
Checkpoint number: ckpt.234
value1: 20
value2: 25
如何从文件中提取数据并在新行中按以下格式打印?
ckpt.123,10,10
ckpt.234,20,25
我尝试了以下 awk 命令,但没有全部打印出来。
awk < awk_test.txt '/ckpt/a=$NF /value1/b=$NF /value2/c=$NF END printf "%s,%s,%s\n",a,b,c'
【问题讨论】:
【参考方案1】:$ awk '/^Check/if (NR>1) print rec; rec=$NF; next rec = rec "," $NF ENDprint rec' file
ckpt.123,10,10
ckpt.234,20,25
【讨论】:
【参考方案2】:对于 GNU awk,Record Separator RS 可以设置为任何正则表达式,在这种情况下,可以设置为 Checkpoint number
。字段分隔符 FS 可以设置为:
或\n
。
这样行就变成了字段。
gawk 'BEGIN RS="Checkpoint number" ; FS=": |\n"; OFS="," if(NR > 1) print $2,$4,$6 ' text.txt
结果:
ckpt.123,10,10
ckpt.234,20,25
注意:POSIX 仅支持单个字符作为 RS。感谢@EdMorton 和@Rafael 的cmets。我不习惯考虑便携性。
【讨论】:
wrtRecord Separator RS can be set to any string
- 没有。在 POSIX awks 中,RS 是单个字符,而在 GNU awk 中,它是一个多字符正则表达式,它绝不是文字多字符字符串。
@EdMorton 在考虑可移植性时,这绝对是一个重要因素。在为自己辩护时,他调用了gawk
,但从未说过awk
。
@Rafael 调用 gawk 并没有告诉读者该代码只能在 gawk 中工作,它只是告诉读者张贴者恰好使用 gawk,即使在 gawk 中,RS 也不是“ string" 这是一个正则表达式。【参考方案3】:
您只能打印END
块中的数据。当然,您需要结束块,但是当您到达ckpt
行并且已经积累了一些数据时,您还需要打印。这导致:
awk '/ckpt/ if (a != "") printf "%s,%s,%s\n", a, b, c; a = $NF
/value1/ b = $NF
/value2/ c = $NF
END printf "%s,%s,%s\n", a, b, c '
当用于您的样本数据时,会产生:
ckpt.123,10,10
ckpt.234,20,25
或者你甚至可以使用一个函数来封装打印:
awk 'function print_it() printf "%s,%s,%s\n", a, b, c;
/ckpt/ if (a != "") print_it(); a = $NF
/value1/ b = $NF
/value2/ c = $NF
END print_it() '
这样做的好处是可以确保在需要打印的两个地方使用相同的打印代码。
【讨论】:
【参考方案4】:这可能对你有用(GNU sed):
sed -r 's/.*: //;N;N;s/\n[^:]*: /,/g' file
删除标签并用逗号替换换行符以换行模三。
【讨论】:
以上是关于使用 awk/sed/bash 检索所有必填字段后打印的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Python 中实现常见的 bash 习语? [关闭]
提交联系表 7 后如何防止在未输入必填字段的情况下重定向到某个 URL