正则表达式和 Sed/Perl:匹配前面没有另一个词的词

jon*_*scb 12 sed perl regular-expression

我想使用sedperl替换前面没有某个词的所有出现的词。

例如,我有一个包含电影情节的文本文件,我想用他们的名字替换所有出现的角色姓氏,但前提是他们的名字不紧跟在他们的姓氏之前。

示例文本可能如下所示:

John Smith and Jane Johnson talk about Smith's car.
Run Code Online (Sandbox Code Playgroud)

我希望它看起来像这样:

John Smith and Jane Johnson talk about John's car.
Run Code Online (Sandbox Code Playgroud)

如果我只是这样做sed 's/Smith/John/' file,那么我会:

John John and Jane Johnson talk about John's car.
Run Code Online (Sandbox Code Playgroud)

姓氏之前的名字将始终相同。我不必处理John SmithFrank Smith。我只需要一种方法来匹配SmithJohn前面没有的。

man*_*ork 9

使用正则表达式能够回顾的任何语言都会很容易。当然,Perl 是第一个:

perl -pe 's/(?<!John\W)Smith/John/g' <<< "John Smith and Jane Johnson talk about Smith's car."
Run Code Online (Sandbox Code Playgroud)

弱点是在“John”和“Smith”之间有一个以上的非单词字符。不幸的是,像+for\W这样的量词会引发“未实现可变长度后视”错误。


Pet*_*r.O 7

编辑..重新你的评论..这是一个新的脚本,它不关心(例如)威廉史密斯。它暂时混淆了保持为Smith(不变)的模式。

sed -r 's/\<(John) (Smith)\>/\1\x01x\2/g; 
        s/\<Smith\>/John/g;  s/\x01x/ /g'
Run Code Online (Sandbox Code Playgroud)

如果你担心先生。 Mrs Mrs...那么这有效。

sed -r 's/\<(John|((M(r|rs|s))\.?)) (Smith)\>/\1\x01x\5/g
        s/\<Smith\>/John/g; s/\x01x/ /g'
Run Code Online (Sandbox Code Playgroud)

您可以通过将他的名字添加到列表来满足威廉的需求,例如。
sed -r 's/\<(William|John|...


这是原始脚本

sed -r 's/(^|[[:punct:]] |\<[a-z]+ )(Smith\>)/\1John/'
Run Code Online (Sandbox Code Playgroud)