10
zzzzzzzzz
aaaaaaaaa
bbbbbbbbb &
ccccccccc &
ddddddddd
hhhhhhhhh
eeeeeeeee
fffffffff &
ggggggggg &

in the above line, what i want is to grep/sed/awk (any method is fine) line that have & sign plus one line on top of them. so for example the desired output will look like :

aaaaaaaaa
bbbbbbbbb &
ccccccccc &
eeeeeeeee
fffffffff &
ggggggggg &

following is what i have tried with no luck.

egrep "&" | -b 1 file.txt

2 Answers 2

20

You can do:

grep -B 1 '&$' your_file

This will look for lines ending in &, remove $ to match lines with & anywhere in them.

The -B switch tells grep to output "context" lines that come before the lines that match. In this case, since you want one line of context, you need -B 1.

This switch is available in GNU grep but is not in the POSIX standard, though.

Here's a simple sed solution that should help in case you don't have GNU grep:

sed -n '/&/!N;/&/p' your_file

How it works

  • The -n switch suppresses the default "print" action of sed
  • /&/!N means: if the current line doesn't contain &, append the next line to the pattern space.
  • /&/p means: match & and print the pattern space.
2
  • 2
    @RanaKhan Welcome to Stack Exchange :) I'm glad I could help. Please don't forget to mark this answer as accepted (use the tick mark below the vote buttons next to the answer) if it helped solve your problem so that others browsing the site know that this problem is solved.
    – Joseph R.
    Commented Nov 5, 2013 at 22:09
  • +1 for the variant when GNU/grep is not available, thanks!
    – ckujau
    Commented Feb 16, 2020 at 4:32
4

Here's how to emulate grep -B1 with sed:

sed '$!N;/pattern/P;D' infile

It's very similar to the one here. Just like the other one, it reads in the Next line but this time, it Prints up to first \newline if the pattern space matches, and then, just like the other one, Deletes up to first \newline and restarts the cycle. So with your sample input:

sed '$!N;/&/P;D' infile

outputs:

aaaaaaaaa
bbbbbbbbb &
ccccccccc &
eeeeeeeee
fffffffff &
ggggggggg &

Again, to see how it works, add l before and after the N to look at the pattern space::

sed 'l;$!N;l;/&/P;D' infile

e.g. with a sample file:

zzzz &
aaaa
bbbb
cccc &
dddd &
hhhh
eeee
ffff &
gggg &

these are the commands that sed executes and corresponding output:

cmd        output            cmd
l       zzzz &$               N # read in the next line
l       zzzz &\naaaa$         # pattern space matches so print up to \n
P       zzzz &                D # delete up to \n 
l       aaaa$                 N # read in the next line
l       aaaa\nbbbb$           D # delete up to \n (no match so no P)
l       bbbb$                 N # read in the next line
l       bbbb\ncccc &$         # pattern space matches so print up to \n
P       bbbb                  D # delete up to \n
l       cccc &$               N # read in the next line
l       cccc &\ndddd &$       # pattern space matches so print up to \n
P       cccc &                D # delete up to \n
l       dddd &$               N # read in the next line
l       dddd &\nhhhh$         # pattern space matches so print up to \n
P       dddd &                D # delete up to \n
l       hhhh$                 N # read in the next line
l       hhhh\neeee$           D # delete up to \n (no match so no P)
l       eeee$                 N # read in the next line
l       eeee\nffff &$         # pattern space matches so print up to \n
P       eeee                  D # delete up to \n
l       ffff &$               N # read in the next line
l       ffff &\ngggg &$       # pattern space matches so print up to \n
P       ffff &                D # delete up to \n
l       gggg &$               # last line so no N 
l       gggg &$               # pattern space matches so print up to \n
P       gggg &                D # delete up to \n

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .