使用sed进行反向查找和替换

5
如何在字符串中搜索特定单词/模式的最后一个出现位置并将其替换为另一个单词?例如,搜索词为“aaa”,替换词为“zzz”。输入为“aaa bbb ccc bbb aaa”,期望输出为“aaa bbb ccc bbb zzz”。命令“s/aaa/zzz/”只能替换第一个匹配项。是否有其他选项可以进行反向搜索?

根据您的示例,您可以将搜索模式锚定到行末,即 echo "aaa bbb ccc bbb aaa" | sed 's/aaa$/zzz/',但这被称为脆弱解决方案。 (您可以使用 's/aaa[ ]*$/zzz/' 考虑行末的额外空格,但仍然脆弱;-))。祝好运。 - shellter
@shellter 如果我想要将最后一个出现的 bbb 替换为 yyy 呢? :P - jkshah
这就是为什么我说这是一个脆弱的解决方案,容易受到规格变更的威胁 ;-). 很高兴你得到了答案。 - shellter
2个回答

5

使用 sed:

x='aaa bbb ccc bbb aaa'
sed 's/\(.*\)bbb/\1zzz/' <<< "$x"

aaa bbb ccc zzz aaa

使用perl命令行:

sed不支持预测先行断言,如果您想尝试使用perl:

perl -pe 's/aaa(?!.*?aaa)/zzz/' <<< "$x"

aaa bbb ccc bbb zzz

这不是很丑吗?我的意思是我期望有一些开关或选项只是为了反向搜索。此外,对于非常长的行,在性能方面,这实际上会在整个字符串中进行搜索吗? - jkshah
丑陋???至少它能够完成任务,而不需要编写一些复杂的命令。你的代码有多长呢? - anubhava
你的解决方案完美地运作了,毫无疑问。我只是出于好奇才提出这个问题。虽然我没有精确计算长度,但当换行时它确实填满了整个屏幕! - jkshah
感谢确认。非常感谢您的回复。 - jkshah
顺便提一下,我也提供了一个sed解决方案,请检查。 - anubhava
2
sed的解决方案经常很丑陋。 - Gavin Smith

1

如果我们反转字符串,使用sed更改反转字符串中的第一个出现的字符,然后再将结果反转回正常顺序,会发生什么:

#!/bin/bash

str="aaa bbb ccc bbb aaa"
echo "${str}" | rev | sed 's/bbb/zzz/' | rev

如果我们只需要替换一个符号,它可以正常工作。对于单词,您需要同时反转模式和替换单词。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接