区切られたテキストデータがあり、"|"
列値を変換したいと思います。
$ cat infile
Mark|father
Jason|SOn
Jose|son
Steffy|daugHter
(父|息子|娘)の事例を無感覚に検索し、父が父の場合、息子が息子の場合、娘が娘の場合を変えたい。
したがって、出力ファイルは次のようになります。
$ cat outfile
Mark Father
Jason Son
Jose Son
Steffy Daughter
IGNORECASEとsubまたはgsubのさまざまな組み合わせを試していますが、すべてのエントリがinfileとして印刷されます。
ベストアンサー1
これは試された答えです質問の元のバージョン。それ以来、要件が変更されました。
sed
GNU実装の利点の1つは次のとおりです。
$ sed -E 's/(^|\s)(son|daughter|father)(\s|$)/\1\L\u\2\3/i' < file
Mark Father
Jason Son
Jose Son
Steffy Daughter
正規表現は、これら3つの単語のいずれかに一致しますが、その単語の前に空白以外の文字がない場合にのみ一致します。
\L
単語全体を小文字に変換し、最初の文字だけを大文字\u
に変換します(これはex
70年代のものですが、vi
残念ながらparまでではありませんsed
)。
perl -pe
代わりに、同じものを使用できます(GNUよりもsed -E
多くのシステムで潜在的に移植性が高い)。ただし、次のように単純化できます。perl
sed
perl
perl -pe 's/(?<!\S)(son|daughter|father)(?!\S)/\L\u$&/i'
つまり、これらの文字列がスペースで区切られた長い単語(Jason
入力など)の一部ではないことを確認するには、負のナビゲーション演算子を使用します。 sed の\b
inperl
および word 境界演算子も参照してください。しかし、これは文字を構成する単語ではないので、孫を孫に変えるのと似ています。\<
\>
(?!\w)
-
各行は最大1回だけ変更できます。すべての項目を置き換えるには、g
上記のフラグにフラグを追加できますperl
。最初の一致が次に置き換えられ、検索が続行され、以前の一致が見つからないため、1つに追加するとsed
一部が失われる可能性があります。この問題は、事前にすべての空白文字を倍増し、後で復元することで解決できます。Mark son SON sOn
" son "
" Son "
sed
"SON sOn"
\s
SON
sed -E 's/\s/&&/g
s/(^|\s)(son|daughter|father)(\s|$)/\1\L\u\2\3/ig
s/(\s)\1/\1/g'
しかし、これは少し複雑すぎるようになりました。