How to grep for text in a file and display the paragraph that has the text?
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
Related videos on Youtube
Jaya William
Updated on September 18, 2022Comments
-
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 almost 11 yearsYou 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 Путлер Капут 六四事 almost 9 years
-
-
jasonwryan almost 11 years+1 for an elegant solution. You don't need to redirect the file though...
-
tripleee almost 11 yearsThis can be simplified by using options and shorthands, and losing the useless use of
cat
;perl -00 -ne 'print if /42B/' file
-
llua almost 11 yearsfingers were on autopilot.
-
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 runningawk
or performing other redirections if the input file can't be opened. -
mivk over 8 yearsOr shorter (and thus more readable), as triplee wrote in a comment:
perl -00 -ne 'print if /42B/' file
. -
IllvilJa over 5 yearsHaving the -p flag would be wonderful. Especially if used together with -v so you could exclude entire paragraphs from output.