用 sed 替换文件中最后出现的文本

Posted

技术标签:

【中文标题】用 sed 替换文件中最后出现的文本【英文标题】:Replace last text ocurrence in a file with sed 【发布时间】:2021-11-16 00:28:38 【问题描述】:

我想替换文件中最后出现的单词。

hello
bye
bye
bye
hello

我可以通过指示行号来替换它。

sed -i '4 s/bye/adieu' file

另外,如果出现在最后一行。

sed -i '$ s/hello/salut' file

但是,我怎样才能找到并替换最后一个bye而不指明行号?

【问题讨论】:

这能回答你的问题吗? KSH: sed command to search and replace last occurrence of a string in a file 感谢维克托。如提供链接的帖子中所述,使用 tail -2 文件 | sed 's/bye/adieu/g' 可以,但是需要知道最后一次出现的位置。 【参考方案1】:

这有点粗糙,可能不建议用于大文件,但它应该可以工作:

sed -zE '$ s/(.*)bye/\1adieu/' file

-z 使 Sed 将整个文件视为一行,其中穿插有 \n-E 是使用 () 而不是 \(\)

如果有可能一行包含bye 但不仅仅是bye,如goodbye/good bye/whatever,那么您可以使用

sed -zE '$ s/(.*)(^|\n)bye($|\n)/\1adieu/' file

【讨论】:

对于我目前的需求,它可以完美运行。谢谢恩利科。 @Jota,在这种情况下,为什么不也给我点个赞呢?【参考方案2】:

使用tac | gnu-sed | sed 的一种可能解决方案:

tac file | sed '0,/^bye$/ s//adieu/' | tac

hello
bye
bye
adieu
hello

详情:

tac 反向打印文件 0,/^bye$/ 匹配从开头到第一次出现 bye 行的行 s//adieu/adieu 替换该行 tac 再次反向打印文件以获得原始订单

或者awk 解决方案适用于awk 的任何版本:

awk 'FNR == NR if ($0 == "bye") last = FNR; next
FNR == last $0 = "adieu" 1' file file

hello
bye
bye
adieu
hello

【讨论】:

我一直在使用 tac,但它只显示输出,不编辑文件。谢谢阿努巴瓦。 保存更改使用:tac file | sed '0,/^bye$/ s//adieu/' | tac > _tmp && mv _tmp file

以上是关于用 sed 替换文件中最后出现的文本的主要内容,如果未能解决你的问题,请参考以下文章

linux下sed命令对文件执行文本替换

linux sed 替换

Bash:如何使用 sed 仅替换文件中的最后一次出现?

sed匹配全行,行首,行尾后替换或添加字符

sed:无法使用变量替换最新出现的文本,包括“-”破折号

用sed 怎么替换包含换行符\n的文本.比如这些