从匹配的模式中替换第 n 行

smc*_*smc 5 shell sed shell-script

我有以下文本文件。

banana
apple
juice
mango
something
Run Code Online (Sandbox Code Playgroud)

我正在搜索 pattern juice,我想以相反的顺序从该匹配模式中找到第二行(即匹配模式上方的 2 行)并将其替换为coconut.

预期输出:

coconut
apple
juice
mango
something
Run Code Online (Sandbox Code Playgroud)

我尝试了以下操作,但它只是删除了上面两行,而不是我正在寻找的那一行。

tac foo.txt |sed '/juice/I,+2 d' |tac
mango
something
Run Code Online (Sandbox Code Playgroud)

我认为调整上面的脚本可以完成这项工作,但我不确定。

注意:匹配不会再次发生,也不需要完全匹配(也就是说,匹配也可以在长行中找到)。匹配应该区分大小写。

Ain*_*r-G 6

如果ed没问题,你需要编辑一个文件,而不是一个流,而且只有一个 juice

$ more <<-EOF | ed -s ./tmp.txt
	/juice/
	-2
	c
	coconut
	.
	w
	q
EOF
$
Run Code Online (Sandbox Code Playgroud)

找到这条线,向上走两条线,change、 write 和 quit。


@d-ben-knoble 在评论中建议的更紧凑的变体:

$ printf '%s\n' '/^juice$/-2s/.*/coconut/' w q | ed -s ./tmp.txt
Run Code Online (Sandbox Code Playgroud)


Qua*_*odo 3

按照你的做法,

tac file|sed '/juice/{n;n;s/.*/coconut/}'|tac
Run Code Online (Sandbox Code Playgroud)
  • /juice/与 匹配一行juice
  • n;n;打印当前行和下一行。
  • s/.*/coconut/进行替换。

显然你有GNU sed,所以你也可以使用-z将整个文件放入内存并直接编辑上面的第二行juice,

sed -rz 's/[^\n]*(\n[^\n]*\n[^\n]*juice)/coconut\1/' file
Run Code Online (Sandbox Code Playgroud)

[^\n]表示“不是换行符”,括号捕获由反向()引用复制的组。\1