如何使用awk打印贪婪的行

时间:2015-04-30 21:19:33

标签: regex bash search awk range

我遇到了以下问题,并没有找到解决方案,也没有为什么awk会以这种奇怪的方式行事。

所以,让我说我在文件中有以下文字:

startcue
This shouldn't be found.

startcue
This is the text I want to find.
endcue

startcue
This shouldn't be found either.

我想找到线条" startcue","这是我想找的文字。"和" endcue"。

我天真地认为通过awk' / startcue /,/ endcue /'进行简单的范围搜索。会这样做,但这打印出整个文件。我想awk以某种方式找到了第一个范围,但是当第三个startcue触发了行的打印时,它会打印所有行直到文件结尾(但是,这对我来说似乎有点奇怪)。

现在问的问题是:我怎么能得到awk才能打印出我想要的线条?也许还有一个额外的问题:任何人都可以解释awk的行为吗?

由于

3 个答案:

答案 0 :(得分:3)

$ awk '/startcue/{f=1; buf=""} f{buf = buf $0 RS} /endcue/{printf "%s",buf; f=0}' file
startcue
This is the text I want to find.
endcue

答案 1 :(得分:2)

这是一种简单的方法。
由于数据是用空行分隔的,我将RS设置为空 这使得awk可以处理块中的数据 然后找到以startcue开头并以endcue

结尾的所有块
awk -v RS="" '/^startcue/ && /endcue$/' file
startcue
This is the text I want to find.
endcue

如果startcueendcue始终是起始行和结束行,并且只在块中出现一次,则应执行以下操作:( PS测试确实表明如果有更多或更多或块中的命中次数较少。如果找到startclue和endcue,则始终打印块。

awk -v RS="" '/startcue/ && /endcue/' file
startcue
This is the text I want to find.
endcue

这也应该有效:

awk -v RS="" '/startcue.*endcue/' file
startcue
This is the text I want to find.
endcue

答案 2 :(得分:1)

要总结问题,您需要从startcue到endcue 的打印行,但如果缺少endcue 则不需要。艾德莫顿的方法很好。这是另一种方法:

$ tac file | awk '/endcue/,/startcue/' | tac
startcue
This is the text I want to find.
endcue

如何运作

  • tac file

    以相反顺序打印行。 taccat类似,只是行的顺序相反。

  • awk '/endcue/,/startcue/'

    这将打印从endcue开始并使用startcue完成的所有行。这样做时,不会打印缺少结束的段落。

  • tac

    这会再次反转这些行,以便按正确的顺序返回。

awk范围如何工作

考虑:

 awk '/startcue/,/endcue/' file

这会告诉awk如果找到startcue则开始打印并继续打印,直到找到endcue。这正是它在您的文件中所做的。

没有隐含的规则,范围/startcue/,/endcue/本身不能包含startcue的多个实例。 awk只是在第一次出现startcue时开始打印,并一直持续到找到endcue