Find each line matching a pattern but print only the line above it

awkgrepsedtext processing

I need to find a string and need to print the line above it.

case1: The same line won't have the more than one matching pattern

ie)
consider a file containing

$cat > para
returns between the paragaraphs
italic or bold    
quotes by placing
italic

Here i need to find for italic, and i need to get the output as below

returns between the paragaraphs
quotes by placing

How can i get the output like this?

Best Answer

If the pattern cannot occur on consecutive lines you can simply run

sed '$!N;/.*\n.*PATTERN.*/P;D' infile

I've explained here how the N;P;D cycle works. The difference is that here the first line in the pattern space is printed only if the second one matches, otherwise it's deleted.


If the pattern can occur on consecutive lines the above solution will print a line that matches if it's followed by another line that matches.
To ignore consecutive matches add a second condition to print the first line in the pattern space only if it doesn't match:

sed '$!N;/.*\n.*PATTERN.*/{/.*PATTERN.*\n.*/!P;};D' infile

Another way, using the hold buffer.
If you want to ignore consecutive matches:

sed '/PATTERN/!{              # if line doesn't match PATTERN
h                             # copy pattern space content over the hold buffer
d                             # delete pattern space
}
//{                           # if line matches PATTERN
x                             # exchange pattern space with hold space
//d                           # if line matches PATTERN delete it
}' infile

or, in one line

sed '/PATTERN/!{h;d;};//{x;//d;}' infile

If you don't want to ignore consecutive matches:

sed '/PATTERN/!{              # if line doesn't match PATTERN
h                             # copy pattern space content over the hold buffer
d                             # delete pattern space
}
//x                           # if line matches PATTERN exchange buffers
' infile 

or, in one line

sed '/PATTERN/!{h;d;};//x' infile

Though keep in mind the solutions that use the hold buffer will print a leading empty line if the first line in your file matches.