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