如何使用awk打印最后的图案范围?

如何使用awk打印最后的图案范围?,awk,Awk,我的文件如下: /开始模式/第一次匹配 /结束模式/ 其他文本 /开始模式/第二次匹配 /结束模式/ 其他文本 /开始模式/这是我想要的模式 要打印出来吗/end 模式/其他文本 如何使用awk打印最后一个匹配?我只知道如何打印所有这些匹配项。存储当前匹配项并使用结束块打印: awk '/end pattern/{flag=0} flag{m=$0} /begin pattern/{flag =1} END{print m}' file 如果在/begin pattern/和/end pat

我的文件如下:

/开始模式/
第一次匹配
/结束模式/

其他文本

/开始模式/
第二次匹配
/结束模式/

其他文本

/开始模式/
这是我想要的模式 要打印出来吗
/end 模式/
其他文本


如何使用awk打印最后一个匹配?我只知道如何打印所有这些匹配项。

存储当前匹配项并使用结束块打印:

awk '/end pattern/{flag=0} flag{m=$0} /begin pattern/{flag =1}  END{print m}' file

如果在/begin pattern/和/end pattern/之间只有一行,则此操作有效,具体取决于是否要打印包含分隔符的行:

awk 'END { print r } 
/end pattern/ { f = x }
/begin pattern/ { f = 1; r = x }
f++ > 1 { r = r ? r RS $0 : $0 }
' infile 
$ 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/
或:


这确保了打印的是一个以
begin pattern
开始、以
end pattern
结束的块,因此,如果在输入文件的末尾存在
start pattern
之后,您不必只打印一堆行,而不打印任何
end pattern
。它还可以确保在输入中不存在匹配块的情况下不打印空行。

使用
x
的方式很有趣。在
/end模式/
中,它实际上是
0
;在
/begin模式/
中,它实际上是
(空字符串)。它从来没有设置为任何东西。在我看来,使用
0
会更清晰。它当然会起作用,但在脚本的开头看到END语句而不是在脚本的结尾,这很奇怪。此外,我盯着这个问题看了很久,试图找出
r
x
之间的区别,然后才意识到您正在使用未设置变量
x
作为空字符串!不要把你的代码弄糊涂了,因为为了节省输入更多的字符-
f
是一个数字,
r
是一个字符串,而不是用一个未设置的变量
x
r=x
,只要使用
f=0
r=”“
就可以了。现在我明白代码在做什么了,它会失败的(跳过它们)当
begin pattern
之后的第一行为
0
或为空时。当不存在
end pattern
时,它还会在文件末尾打印
begin pattern
之后的任何行,而不是打印
begin pattern
end pattern
之间的最后一组行,并打印一个空行如果输入中不存在匹配的块。@埃德蒙顿:这很微妙。
r=r?r$0:$0
如果前面的行包含
0
(或
00
0.0
或“
0
”等),或者如果它是空的(但如果该行只包含空白的话,则不计算
r
,则计算为“false”)。修复此问题需要更多的工程工作。
f++>1
条件确保忽略开始模式行。使用
f
f==1
将在输出中包含开始模式。要在输出中包含结束模式,必须在结束模式操作中将
$0
添加到
r
。@JonathanLeffler这种“在一个范围内打印文本”的东西是比听起来要复杂得多的东西之一。我们甚至没有涉及到部分匹配、全行匹配、全词匹配、字符串与regexp匹配,以及开始和结束字符串可能出现在同一行或中间行的情况。很容易想出一个“解决方案”这适用于已发布的示例输入集,然后在6个月后在实际客户数据上运行时崩溃!如果您使用
awk'/begin pattern/,/end pattern/,
,并且在末尾附近有一个begin pattern,后面没有结束模式,那么该材料将被打印出来。问题并没有解决发生这种情况时所需的内容-这将是r请看第二个输入示例。您记录了您认为“不完整块”是不可打印的内容-是否值得记录在打印不完整块时该怎么做?我认为它变成了
END{if(f)last=rec;printf“%s”,last}
,不是吗?至少对于“无定界符”代码来说是这样。我从不使用范围表达式,因为它们会为琐碎的问题保存几个字符,然后在问题变得稍微有趣时需要完全重写或复制条件,所以在我的心目中,它们根本不值得麻烦。如果一个不完整的bl我想你根本没有
last
变量,只需要打印
rec
。啊-是的,你不使用
last
而只是打印
rec
可能是对的。
$ 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