web-dev-qa-db-ja.com

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

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 SmithFrank Smithを処理する必要はありません。前にSmithがないJohnに一致する方法が必要です。

11
jonescb

正規表現が後ろを見ることができる言語であれば、簡単です。もちろん、Perlはリストの最初です。

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

弱点は、「John」と「Smith」の間に複数の非Word文字があることです。残念ながら、+\Wのような数量詞を使用すると、「可変長の後読みが実装されていません」というエラーが発生します。

8
manatwork

[〜#〜] edit [〜#〜] .. re your comment ..これは、(たとえば)William Smithに関係のない新しいスクリプトです。 Smith(変更なし)として保持するパターンを一時的に難読化します。

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

Mr。Mrs Mrs ...が気になる場合は、これでうまくいきます。

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

orリストに彼の名前を追加することで、Williamに対応できます。
sed -r 's/\<(William|John|...


これは元のスクリプトです

sed -r 's/(^|[[:punct:]] |\<[a-z]+ )(Smith\>)/\1John/'
6
Peter.O
 sed -r 's/([^John] )Smith/\1John/g;s/([^Jane] )Johnson/\1Jane/g'

()は、LastNameの前に非Firstnameをキャプチャするので、それらは置換で後方参照されます。

編集

@ manatwork、gilles

あなたが正しい。いかがですか

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

これでうまくいくようです。

1
ata