How can I set the grep after context to be “until

2020-05-14 03:55发布

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"?

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....

4条回答
等我变得足够好
2楼-- · 2020-05-14 04:25

Here's a (tested) awk solution, separated onto multiple lines for readability:

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}

Explanation:

  • awk: invoke the awk tool - it evaluates the input one line at a time sequentially.
  • '...'.: everything enclosed by the single quotes is given to awk as 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_print flag
  • do_print==1 {print}: if the do_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 the do_print flag to stop printing when we see a line with NF == 0
查看更多
做自己的国王
3楼-- · 2020-05-14 04:29

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.

查看更多
放我归山
4楼-- · 2020-05-14 04:33

It sounds like you need sed:

sed -n '/pattern/,/^$/p' file

Don't print by default (-n). For lines that match /pattern/ up to an empty line /^$/, print.

查看更多
看我几分像从前
5楼-- · 2020-05-14 04:35

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:

$ 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:

$ awk '/bar/' RS= demo.ini 
[bar]
eee = 8
fff = 0
ggg = 1
$ awk '/fff/' RS= demo.ini 
[bar]
eee = 8
fff = 0
ggg = 1
查看更多
登录 后发表回答