使用 sed 或 awk 按照匹配模式打印一行 [英] Printing with sed or awk a line following a matching pattern
问题描述
问题:我想在包含匹配模式的行之后直接打印一行.
Question: I'd like to print a single line directly following a line that contains a matching pattern.
我的 sed
版本不会采用以下语法(它会在 +1p
上爆炸),这似乎是一个简单的解决方案:
My version of sed
will not take the following syntax (it bombs out on +1p
) which would seem like a simple solution:
sed -n '/ABC/,+1p' infile
我认为 awk
更适合进行多行处理,但我不知道该怎么做.
I assume awk
would be better to do multiline processing, but I am not sure how to do it.
推荐答案
永远不要使用模式"这个词;因为它非常模棱两可.始终使用字符串"或正则表达式"(或在 shell 中的globbing 模式"),无论你是什么意思.
Never use the word "pattern" as is it highly ambiguous. Always use "string" or "regexp" (or in shell "globbing pattern"), whichever it is you really mean.
您想要的具体答案是:
awk 'f{print;f=0} /regexp/{f=1}' file
或者在正则表达式之后专门针对第 N 个记录的更通用的解决方案(下面的成语c"):
or specializing the more general solution of the Nth record after a regexp (idiom "c" below):
awk 'c&&!--c; /regexp/{c=1}' file
以下习语描述了如何在给定特定正则表达式的情况下选择要匹配的记录范围:
The following idioms describe how to select a range of records given a specific regexp to match:
a) 打印一些正则表达式中的所有记录:
a) Print all records from some regexp:
awk '/regexp/{f=1}f' file
b) 在一些正则表达式后打印所有记录:
b) Print all records after some regexp:
awk 'f;/regexp/{f=1}' file
c) 在一些正则表达式之后打印第 N 条记录:
c) Print the Nth record after some regexp:
awk 'c&&!--c;/regexp/{c=N}' file
d) 在某些正则表达式之后打印除第 N 条记录以外的所有记录:
d) Print every record except the Nth record after some regexp:
awk 'c&&!--c{next}/regexp/{c=N}1' file
e) 在一些正则表达式后打印 N 条记录:
e) Print the N records after some regexp:
awk 'c&&c--;/regexp/{c=N}' file
f) 在一些正则表达式后打印除 N 条记录以外的所有记录:
f) Print every record except the N records after some regexp:
awk 'c&&c--{next}/regexp/{c=N}1' file
g) 从一些正则表达式打印 N 条记录:
g) Print the N records from some regexp:
awk '/regexp/{c=N}c&&c--' file
我将变量名从f"更改为为找到"到c"用于计数"在哪里更合适,因为这更能表达变量的实际含义.
I changed the variable name from "f" for "found" to "c" for "count" where appropriate as that's more expressive of what the variable actually IS.
f
是 found
的缩写.它是一个布尔标志,当我在输入 (/regexp/{f=1}
) 中找到与正则表达式 regexp 匹配的字符串时,我将其设置为 1(真).您在每个脚本中看到 f
的另一个地方是它作为条件进行测试,当 true 导致 awk 执行其打印当前记录的默认操作时.所以输入记录只有在我们看到正则表达式并将 f
设置为 1/true 后才会得到输出.
f
is short for found
. Its a boolean flag that I'm setting to 1 (true) when I find a string matching the regular expression regexp in the input (/regexp/{f=1}
). The other place you see f
on it's own in each script it's being tested as a condition and when true causes awk to execute its default action of printing the current record. So input records only get output after we see regexp and set f
to 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
达到零并继续递减,所以它经常回绕并再次变为正数.
c && c-- { foo }
means "if c
is non-zero then decrement it and if it's still non-zero then execute foo
" so if c
starts at 3 then it'll be decremented to 2 and then foo
executed, and on the next input line c
is now 2 so it'll be decremented to 1 and then foo
executed again, and on the next input line c
is now 1 so it'll be decremented to 0 but this time foo
will not be executed because 0 is a false condition. We do c && c--
instead of just testing for c-- > 0
so we can't run into a case with a huge input file where c
hits zero and continues getting decremented so often it wraps around and becomes positive again.
这篇关于使用 sed 或 awk 按照匹配模式打印一行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!