【发布时间】:2020-05-25 05:20:13
【问题描述】:
我的文件是这样的:
/开始模式/
第一个匹配
/结束模式/其他文字
/开始模式/
第二场比赛
/结束模式/其他文字
/begin pattern/
这是我的 想打印出来
/end 图案/
其他文字
如何使用 awk 打印出最后一场比赛?我只知道如何打印出所有这些匹配项。
【问题讨论】:
标签: awk
我的文件是这样的:
/开始模式/
第一个匹配
/结束模式/其他文字
/开始模式/
第二场比赛
/结束模式/其他文字
/begin pattern/
这是我的 想打印出来
/end 图案/
其他文字
如何使用 awk 打印出最后一场比赛?我只知道如何打印出所有这些匹配项。
【问题讨论】:
标签: awk
取决于是否要打印包含分隔符的行:
$ awk '
/begin pattern/ { rec=""; f=1 }
f { rec=rec $0 ORS; if (/end pattern/) {last=rec; f=0} }
END { printf "%s", last }
' file
/begin pattern/
This is the one I want to print out
/end pattern/
或:
$ awk '
f { if (/end pattern/) {last=rec; f=0} rec=rec $0 ORS }
/begin pattern/ { rec=""; f=1 }
END { printf "%s", last }
' file
This is the one I want to print out
这确保您打印的是一个以begin pattern 开头并以end pattern 结尾的块,因此您不会只打印start pattern 后面的一堆行而没有end pattern(如果最后存在)你的输入文件。如果输入中不存在匹配的块,它还可以确保您不会打印空行。
【讨论】:
awk '/begin pattern/,/end pattern/' 并且在结尾附近有一个开始模式,而在它之后没有结束模式,则将打印该材料。这个问题没有解决发生这种情况时需要什么——它需要第二个示例输入。你记录了你认为“不完整的块”是不应该打印的东西——如果应该打印不完整的块,是否值得记录该怎么做?我认为它变成了END { if (f) last = rec; printf "%s", last },不是吗——至少对于“无分隔符”代码而言。
last 变量,只需打印rec。
last 而只是打印 rec。
awk 'END { print r }
/end pattern/ { f = x }
/begin pattern/ { f = 1; r = x }
f++ > 1 { r = r ? r RS $0 : $0 }
' infile
【讨论】:
x 的使用方式很有趣。在/end pattern/ 中,实际上是0;在/begin pattern/ 中,它实际上是""(空字符串)。它永远不会被设置为任何东西。 IMO,使用0 和"" 会更清楚。
x 作为空字符串之前,我一直盯着它试图找出r 和x 之间的区别!不要严重混淆您的代码以节省再输入一个字符 - f 是一个数字,r 是一个字符串,所以而不是 f=x 和 r=x 带有未设置的变量 x,只需使用 @987654337 @ 和 r="" 视情况而定。
begin pattern 之后的第一行是0 或为空时,它会失败(跳过它们)。当不存在end pattern 时,它还会打印文件末尾begin pattern 之后的任何行,而不是打印begin pattern 和end pattern 之间的最后一组行,如果输入中不存在匹配块。
0(或00 或0.0 或“0 ”等),或者如果它为空(但不是如果该行仅包含一个空白)。解决这个问题需要更多的工程工作。 f++ > 1 条件确保忽略开始模式行。使用f 或f == 1 将在输出中包含开始模式。要在输出中包含结束模式,您必须在结束模式操作中将 $0 添加到 r。
存储当前匹配并使用 END 块将其打印出来:
awk '/end pattern/{flag=0} flag{m=$0} /begin pattern/{flag =1} END{print m}' file
如果 /begin pattern/ 和 /end pattern/ 之间只有一行,则此方法有效。
【讨论】: