How to grep for text in a file and display the paragraph that has the text?

48,638

Solution 1

With awk

awk -v RS='' '/42B/' file

RS= changes the input record separator from a newline to blank lines. If any field in an record contains /42B/ print the record.

'' (the null string) is a magic value used to represent blank lines according to POSIX:

If RS is null, then records are separated by sequences consisting of a <newline> plus one or more blank lines, leading or trailing blank lines shall not result in empty records at the beginning or end of the input, and a <newline> shall always be a field separator, no matter what the value of FS is.

The output paragraphs will not be separated since the output separator remains a single newline. To ensure that there is a blank line between output paragraphs, set the output record separator to two newlines:

awk -v RS='' -v ORS='\n\n' '/42B/' file

Solution 2

Assuming the data is structured so that it's always the line before and after that you want you can make use of grep's -A (after) and -B (before) switches to tell it to include the 1 line before the match and 1 line after it:

$ grep -A 1 -B 1 "42B" sample.txt
Pseudo name=Apple
Code=42B
state=fault

If you want the same number lines before and after the search term you can use the -C (context) switch:

$ grep -C 1 "42B" sample.txt
Pseudo name=Apple
Code=42B
state=fault

If you'd like to be more stringent when matching the multiple lines you can use the tool pcregrep, to match a pattern over multiple lines:

$ pcregrep -M 'Pseudo.*\n.*42B.*\nstate.*' sample.txt
Pseudo name=Apple
Code=42B
state=fault

The above pattern matches as follows:

  • -M - multiple lines
  • 'Pseudo.*\n.*42B.*\nstate.*' - matches a group of strings where the first string starts with the word "Pseudo" followed by any characters up until a end of line \n, followed by any characters up until the string "42B" followed by any characters up until another end of line (\n), followed by the string "state"followed by any characters.

Solution 3

The grep of some flavours of Unix have the -p flag for "paragraph". I know AIX does.

grep -p 42B <myfile>

would do exactly what you're asking for there. YMMV and GNU grep doesn't have this flag.

Solution 4

There is probably a similarly easy way to do it with awk, but in perl:

cat file | perl -ne 'BEGIN { $/="\n\n" }; print if $_ =~ /42B/;'

That basically says to split the file into chunks delimited by blank lines, then to only print those chunks that match your regular expression.

Solution 5

An other perl solution, without a trailing empty line:

perl -00ne 'if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}' foo

Example

% perl -00ne 'if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}' foo
Pseudo name=Apple
Code=42B
state=fault

% cat foo
Pseudo name=Apple
Code=42B
state=fault

Pseudo name=Prance
Code=43B
state=good
Share:
48,638

Related videos on Youtube

Jaya William
Author by

Jaya William

Updated on September 18, 2022

Comments

  • Jaya William
    Jaya William over 1 year

    Below is the text in the file:

    Pseudo name=Apple
    Code=42B
    state=fault
    
    Pseudo name=Prance
    Code=43B
    state=good
    

    I need to grep for "42B" and get the output from the above text like:

    Pseudo name=Apple
    Code=42B
    state=fault
    

    Does anyone have idea on how to achieve this using grep/awk/sed?

    • slm
      slm almost 11 years
      You tagged this question with just "grep". Are you only looking for "grep" solutions then? In the question you specify awk & sed too. Can we add those tags? I wasn't sure of your intent when I edited the question last night.
    • Ciro Santilli Путлер Капут 六四事
      Ciro Santilli Путлер Капут 六四事 almost 9 years
  • jasonwryan
    jasonwryan almost 11 years
    +1 for an elegant solution. You don't need to redirect the file though...
  • tripleee
    tripleee almost 11 years
    This can be simplified by using options and shorthands, and losing the useless use of cat; perl -00 -ne 'print if /42B/' file
  • llua
    llua almost 11 years
    fingers were on autopilot.
  • Stéphane Chazelas
    Stéphane Chazelas over 8 years
    @jasonwryan, unless you need access to the file name within awk (FILENAME), it's not a bad idea to use redirection as that avoids problems for filename containing = or starting with - (or being -), makes for consistent error messages, and avoids running awk or performing other redirections if the input file can't be opened.
  • mivk
    mivk over 8 years
    Or shorter (and thus more readable), as triplee wrote in a comment: perl -00 -ne 'print if /42B/' file.
  • IllvilJa
    IllvilJa over 5 years
    Having the -p flag would be wonderful. Especially if used together with -v so you could exclude entire paragraphs from output.