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) awksolution, 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 theawktool - it evaluates the input one line at a time sequentially.'...'.: everything enclosed by the single quotes is given toawkas instructions. In this case we perform the quoted instructions on each line./pattern/ {do_print=1}: whenever a line contains "pattern", turn on thedo_printflagdo_print==1 {print}: if thedo_printflag is set to on, print the current line.NF==0 {do_print=0}: NF stands for Number of Fields.awkdelimits 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_printflag 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 inifiles). If you actually want only the after context with awkyou 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

