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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 17:51:24  来源:igfitidea点击:

How can I set the grep after context to be "until the next blank line"?

linuxunixawkgrep

提问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 the awktool - it evaluates the input one line at a time sequentially.
  • '...'.: everything enclosed by the single quotes is given to awkas instructions. In this case we perform the quoted instructions on each line.
  • /pattern/ {do_print=1}: whenever a line contains "pattern", turn on the do_printflag
  • do_print==1 {print}: if the do_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 the do_printflag to stop printing when we see a line with NF == 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