使用sed或awk按照匹配模式打印一行

我想直接在包含匹配模式的行之后打印一行。 我的sed版本不会采用下面的语法(它在+1p上弹出),这看起来像一个简单的解决方案:

 sed -n '/ABC/,+1p' infile 

我假设awk会更好地做多行处理,但我不知道该怎么做。

不要使用“模式”这个词,因为它是高度模糊的。 总是使用“string”或“regexp”(或shell中的“globbing pattern”),无论你是真正的意思。

你想要的具体答案是:

 awk 'f{print;f=0} /regexp/{f=1}' file 

或者在正则表达式(下面的成语“c”)之后专门化第N条记录的更一般的解决方案:

 awk 'c&&!--c; /regexp/{c=1}' file 

下面的习语描述了如何选择给定特定正则表达式匹配的一系列记录:

a)从一些正则表达式打印所有记录:

 awk '/regexp/{f=1}f' file 

b)在正则表达式之后打印所有记录:

 awk 'f;/regexp/{f=1}' file 

c)在正则表达式后打印第N条记录:

 awk 'c&&!--c;/regexp/{c=N}' file 

d)在正则表达式之后打印除第N条记录以外的每条记录:

 awk 'c&&!--c{next}/regexp/{c=N}1' file 

e)打印一些正则表达式后的N个记录:

 awk 'c&&c--;/regexp/{c=N}' file 

f)在一些正则表达式之后打印除N条记录以外的每条记录:

 awk 'c&&c--{next}/regexp/{c=N}1' file 

g)从一些正则表达式打印N个记录:

 awk '/regexp/{c=N}c&&c--' file 

在适当的情况下,我把变量名称从“f”改为“发现”改为“c”,因为这更能表达变量实际上是什么。

那场比赛之后,你很有意思,对吗? 在sed中,可以这样做:

 sed -n '/ABC/{n;p}' infile 

或者,grep的A选项可能是你正在寻找的。

 -A NUM, Print NUM lines of trailing context after matching lines. 

例如,给定以下输入文件:

 foo bar baz bash bongo 

您可以使用以下内容:

 $ grep -A 1 "bar" file bar baz $ sed -n '/bar/{n;p}' file baz 

希望有所帮助。

我需要在模式之后打印所有行(确定Ed,REGEX),所以我决定了这一点:

 sed -n '/pattern/,$p' # prints all lines after ( and including ) the pattern 

但是因为我想打印所有的行后(并排除模式)

 sed -n '/pattern/,$p' | tail -n+2 # all lines after first occurrence of pattern 

我想在你的情况下,你可以在最后加一个head -1

 sed -n '/pattern/,$p' | tail -n+2 | head -1 # prints line after pattern 

awk版本:

 awk '/regexp/ { getline; print $0; }' filetosearch 

其实sed -n '/pattern/{n;p}' filename名将失败,如果pattern匹配continuous行:

 $ seq 15 |sed -n '/1/{n;p}' 2 11 13 15 

预期的答案应该是:

 2 11 12 13 14 15 

我的解决方案是:

 $ sed -n -r 'x;/_/{x;p;x};x;/pattern/!s/.*//;/pattern/s/.*/_/;h' filename 

例如:

 $ seq 15 |sed -n -r 'x;/_/{x;p;x};x;/1/!s/.*//;/1/s/.*/_/;h' 2 11 12 13 14 15 

解释:

  1. x; :在输入的每一行的开头,使用x命令交换pattern spacehold space的内容。
  2. /_/{x;p;x}; :如果实际pattern space包含_ (这只是指示最后一行是否与pattern匹配的indicator ),则使用xcurrent line的实际内容交换到pattern space ,使用p打印current line ,并且x恢复这个操作。
  3. x :恢复pattern space的内容并hold space
  4. /pattern/!s/.*// :如果current line不匹配pattern ,意味着我们不应该打印下一行,然后使用s/.*//命令删除pattern space所有内容。
  5. /pattern/s/.*/_/ :如果current line匹配pattern ,这意味着我们应该打印下一行,那么我们需要设置一个indicator来告诉sed打印下一行,所以使用s/.*/_/pattern space中的所有内容替换为_ (第二个命令将使用它来判断最后一行是否匹配pattern )。
  6. h :用pattern space的内容覆盖hold space pattern space ; 那么, hold space的内容是^_$ ,这意味着current line匹配pattern ,或^$ ,这意味着current line不匹配pattern
  7. 第五步和第六步不能交换,因为在s/.*/_/pattern space不能匹配/pattern/ ,所以必须执行s/.*//

如果模式匹配,将下一行复制到模式缓冲区,删除一个返回,然后退出 – 副作用是打印。

 sed '/pattern/ { N; s/.*\n//; q }; d' 

这可能适用于你(GNU sed):

 sed -n ':a;/regexp/{n;h;p;x;ba}' file 

使用seds grep-like选项-n ,如果当前行包含所需的正则表达式,则将当前行替换为下一行,将该行复制到保留空间(HS),打印行,交换HS的模式空间(PS)并重复。