Shell – Replace nth Line from the Matched Pattern

sedshellshell-script

I have following text file.

banana
apple
juice
mango
something

I am searching for pattern juice, and I want to find the 2nd line from that matching pattern in reverse order (i.e 2 lines above the matching pattern) and replace it with coconut.

Expected output:

coconut
apple
juice
mango
something

I tried with following, but it just deletes the above two line and not the exact one I'm looking for.

tac foo.txt |sed '/juice/I,+2 d' |tac
mango
something

I think tweaking above script would do the job, but I am not sure.

Note:
There will not be any re-occurrence of the match, and it needs not to be an exact match (meaning, the match can be found in a long line as well). The match should be case-sensitive.

Best Answer

Following your approach,

tac file|sed '/juice/{n;n;s/.*/coconut/}'|tac
  • /juice/ matches a line with juice.
  • n;n; prints the current and the next line.
  • s/.*/coconut/ makes the substitution.

Apparently you have GNU sed, so you could also use -z to get the whole file into memory and directly edit the line two above juice,

sed -rz 's/[^\n]*(\n[^\n]*\n[^\n]*juice)/coconut\1/' file

[^\n] means "not a newline" and the parenthesis () capture the group reproduced by the \1 back-reference.

Related Question