Regex&Sed / Perl:他の単語が前に来ない単語の一致

Regex&Sed / Perl:他の単語が前に来ない単語の一致

特定の単語が前に出ていないすべての単語を使用またはsed置換したいです。perl

たとえば、映画のプロットを含むテキストファイルがあり、すべての姓をキャラクターの名前に変更したいとします。ただし、名前が姓の直前に来ない場合にのみ該当します。

サンプルテキストは次のとおりです。

John Smith and Jane Johnson talk about Smith's car.

私はそれが次のように見えるようにしたいです:

John Smith and Jane Johnson talk about John's car.

これにより、次のsed 's/Smith/John/' fileようになります。

John John and Jane Johnson talk about John's car.

姓の前の名前は常に同じです。私はJohn Smithandを扱う必要はありませんFrank SmithSmith以前に存在しなかったマッチング方法が必要です。John

答え1

これは正規表現が逆に見えるすべての言語で簡単です。もちろん、Perlはリストの最初です。

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

弱点は、「ジョン」と「スミス」の間に単語以外の文字が複数あることです。残念ながら、+forなどの数量子は、\W「可変長逆引き参照が実装されていません」というエラーを発生させる可能性があります。

答え2

編集する.. あなたの意見に関して.. これは新しいスクリプトであり(例えば)ウィリアム・スミスには興味がありません。維持するパターンを一時的に難読化します。スミス(絶え間ない)。

sed -r 's/\<(John) (Smith)\>/\1\x01x\2/g; 
        s/\<Smith\>/John/g;  s/\x01x/ /g'

気になるなら先生、奥さん…まあ、これはうまくいきます。

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

あなたは満足することができますウィリアム彼の名前を次に追加またはたとえば、リストを作成します。
sed -r 's/\<(William|John|...


オリジナルスクリプトです

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

答え3

 sed -r 's/([^John] )Smith/\1John/g;s/([^Jane] )Johnson/\1Jane/g'

()は姓の前に名前ではなく名前をキャプチャするため、代替時に逆参照されます。

編集する

@manatwork, ザイルズ

あなたは正しいです。どうですか?

sed -r 's/(John Smith)/temp1/g;s/Smith/John/g;s/temp1/John Smith/g'

これがトリックを行うようです。

関連情報