问题:我想在包含匹配模式的行之后直接打印一行。
我的版本sed
不会采用以下语法(它会爆炸+1p
),这似乎是一个简单的解决方案:
sed -n '/ABC/,+1p' infile
我认为awk
进行多行处理会更好,但我不知道该怎么做。
永远不要使用“模式”这个词,因为它非常模棱两可。始终使用“字符串”或“正则表达式”(或在 shell 中的“通配模式”),无论你真正的意思是什么。
您想要的具体答案是:
awk 'f{print;f=0} /regexp/{f=1}' file
或者在正则表达式之后专门针对第 N 条记录的更一般的解决方案(下面的成语“c”):
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
我将变量名称从“found”的“f”更改为“count”的“c”,因为这更能表达变量的实际含义。
f
是 的缩写found
。它是一个布尔标志,当我在输入 ( ) 中找到与正则表达式 regexp 匹配的字符串时,我将其设置为 1 (true /regexp/{f=1}
)。您在每个脚本中看到f
它自己的另一个地方,它正在作为一个条件进行测试,当它为 true 时,会导致 awk 执行其打印当前记录的默认操作。所以输入记录只有在我们看到 regexp 并设置f
为 1/true 后才会得到输出。
c && c-- { foo }
表示“如果c
非零则递减它,如果它仍然非零则执行foo
”所以如果c
从 3 开始,那么它将递减到 2 然后foo
执行,并且在下一个输入行c
现在是 2 所以它会递减到 1 然后foo
再次执行,并且在下一个输入行c
现在是 1,所以它会递减到 0 但这次foo
不会执行,因为 0 是错误条件。我们这样做c && c--
而不是仅仅测试,c-- > 0
所以我们不能遇到一个输入文件很大的情况,该文件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
希望有帮助。
我需要在模式之后打印所有行(ok 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
我真的应该在这个答案中包含 tlwhitec 的评论(因为他们的 sed-strict 方法比我的建议更优雅):
sed '0,/pattern/d'
上面的脚本删除从第一行开始到(包括)与模式匹配的行的每一行。打印之后的所有行。
awk 版本:
awk '/regexp/ { getline; print $0; }' filetosearch
这可能对您有用(GNU sed):
sed -n ':a;/regexp/{n;h;p;x;ba}' file
使用 seds 类似 grep 的选项-n
,如果当前行包含所需的正则表达式,则将当前行替换为下一行,将该行复制到保留空间 (HS),打印该行,交换 HS 的模式空间 (PS) 并重复.
如果匹配线实际上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};
: ifpattern space
是hold space
实际包含的_
(这只是indicator
表示最后一行是否匹配pattern
),然后用于交换tox
的实际内容,用于打印,并恢复此操作。current line
pattern space
p
current line
x
x
: 恢复 和 中的pattern space
内容hold space
。/pattern/!s/.*//
:如果current line
不匹配pattern
,这意味着我们不应该打印下一行,然后使用s/.*//
命令删除所有内容pattern space
。/pattern/s/.*/_/
: if current line
matchespattern
表示我们应该打印下一行,那么我们需要设置aindicator
来告诉sed
打印下一行,所以使用s/.*/_/
将所有内容替换pattern space
为a _
(第二个命令将使用它来判断最后一行是否匹配pattern
或不)。h
hold space
:用 中的内容覆盖pattern space
; 那么,里面的内容hold space
是^_$
表示current line
匹配的pattern
,或者^$
表示current line
不匹配的pattern
。s/.*/_/
,pattern space
不能匹配/pattern/
,所以s/.*//
必须执行!如果模式匹配,则将下一行复制到模式缓冲区中,删除一个返回,然后退出——副作用是打印。
sed '/pattern/ { N; s/.*\n//; q }; d'
管道一些 grep 可以做到(它在 POSIX shell 和 BusyBox 下运行):
cat my-file | grep -A1 my-regexp | grep -v -- '--' | grep -v my-regexp
-v
将显示不匹配的行