Linux 如何将上下文后的 grep 设置为“直到下一个空行”?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13534306/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I set the grep after context to be "until the next blank line"?
提问by pixelearth
With grep I know how to set the context to a fixed number of lines. Is it possible to show a context based on an arbitrary string condition, like set after-context to "until the next blank line"?
使用 grep 我知道如何将上下文设置为固定数量的行。是否可以根据任意字符串条件显示上下文,例如将 after-context 设置为“直到下一个空行”?
Or possibly some other combination of tools?
或者可能是其他一些工具组合?
Basically I have a log file of contiguous lines, with blank lines separating the "events" I want to search for a string in the log file, but show the whole event....
基本上我有一个连续行的日志文件,用空行分隔“事件”我想在日志文件中搜索一个字符串,但显示整个事件......
回答by Jonathan Leffler
It sounds like you need sed
:
听起来你需要sed
:
sed -n '/pattern/,/^$/p' file
Don't print by default (-n
). For lines that match /pattern/
up to an empty line /^$/
, print.
默认情况下不打印 ( -n
)。对于匹配/pattern/
到空行的行/^$/
,打印。
回答by sampson-chen
Here's a (tested) awk
solution, separated onto multiple lines for readability:
这是一个(经过测试的)awk
解决方案,为了可读性,分成多行:
awk '/pattern/ {do_print=1}
do_print==1 {print}
NF==0 {do_print=0}' input_file
This script will also print the blank line so it's easier to visually separate the different matched blocks. If you don't want the blank line, swap the 2 lines do_print==1 {print}
and NF==0 {do_print=0}
此脚本还将打印空行,以便更容易地在视觉上分隔不同的匹配块。如果您不想要空行,请交换 2 行do_print==1 {print}
并NF==0 {do_print=0}
Explanation:
解释:
awk
: invoke theawk
tool - it evaluates the input one line at a time sequentially.'...'.
: everything enclosed by the single quotes is given toawk
as instructions. In this case we perform the quoted instructions on each line./pattern/ {do_print=1}
: whenever a line contains "pattern
", turn on thedo_print
flagdo_print==1 {print}
: if thedo_print
flag is set to on, print the current line.NF==0 {do_print=0}
: NF stands for Number of Fields.awk
delimits each line by spaces and tabs by default to break a line into fields. In this case trivially a blank line has no fields - so we turn off thedo_print
flag to stop printing when we see a line withNF == 0
awk
:调用该awk
工具 - 它一次按顺序评估输入一行。'...'.
: 单引号括起来的所有内容都awk
作为说明给出。在这种情况下,我们在每一行上执行引用的指令。/pattern/ {do_print=1}
: 每当一行包含“pattern
”时,打开do_print
标志do_print==1 {print}
: 如果do_print
标志设置为 on,则打印当前行。NF==0 {do_print=0}
: NF 代表字段数。awk
默认情况下用空格和制表符分隔每一行以将一行分成多个字段。在这种情况下,一个空白行没有字段 - 所以do_print
当我们看到一行时,我们关闭标志以停止打印NF == 0
回答by William Pursell
A simple solution is:
一个简单的解决方案是:
awk '/pattern/' RS= input-file
Setting RS to the empty string makes awk treat blank lines as the record separator, and the simple rule /pattern/
causes awk to print any record that matches the pattern, which can be any extended regular expression.
将 RS 设置为空字符串使 awk 将空行视为记录分隔符,简单的规则/pattern/
使 awk 打印任何匹配该模式的记录,可以是任何扩展的正则表达式。
回答by htaccess
Personally I like the answer from @William Pursell as the before context is often useful (eg when grepping for things in ini
files). If you actually want only the after context with awk
you can do this:
我个人喜欢@William Pursell 的答案,因为 before 上下文通常很有用(例如,在查找ini
文件中的内容时)。如果你真的只想要 after 上下文,awk
你可以这样做:
$ cat demo.ini
[foo]
aaa = 1
bbb = 2
ccc = 3
[bar]
eee = 8
fff = 0
ggg = 1
[baz]
xxx = 1
yyy = 0
zzz = 2
$ awk '/bar/,/^$/' demo.ini
[bar]
eee = 8
fff = 0
ggg = 1
$ awk '/fff/,/^$/' demo.ini
fff = 0
ggg = 1
$
Compare with the RS=
version:
与RS=
版本对比:
$ awk '/bar/' RS= demo.ini
[bar]
eee = 8
fff = 0
ggg = 1
$ awk '/fff/' RS= demo.ini
[bar]
eee = 8
fff = 0
ggg = 1