Replace nth line from the matched pattern
If ed
is okay, you need to edit a file,
not a stream, and there is only
one juice
:
$ more <<-EOF | ed -s ./tmp.txt
/juice/
-2
c
coconut
.
w
q
EOF
$
Find the line, go two lines up, c
hange,
w
rite, and q
uit.
An even more compact variation, suggested by @d-ben-knoble in the comments:
$ printf '%s\n' '/^juice$/-2s/.*/coconut/' w q | ed -s ./tmp.txt
$ tac file | awk 'c&&!(--c){$0="coconut"} /juice/{c=2} 1' | tac
coconut
apple
juice
mango
something
Following your approach,
tac file|sed '/juice/{n;n;s/.*/coconut/}'|tac
/juice/
matches a line withjuice
.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.