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, change, write, and quit.


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 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.