2 つのファイルがあり、1 つのファイルには文字列のリストが含まれています。
+stringa +Dog +Cat
+cat +Tux +elephant
2 番目のファイル (csv) には次のような内容が含まれます。
"123456 Abc","+Stringx +123","something"
"23456 dEf","+cat +Tux +elephant","Other something"
"34524 xyz","+stringa +Dog +Cat","third something"
結果は次のようになります。
"123456 Abc","+Stringx +123","something"
"23456 dEf","+cat +tux +elephant","Other something"
"34524 xyz","+stringa +dog +cat","third something"
パターンのリストに一致する文字列を小文字に変更するにはどうすればよいですか?
私のカンマ区切り値ファイルには、約 30 列と約 1500 行があります。
答え1
ではGNU sed
、文字列のリストにメタ文字がないと想定され、+
デフォルトのBREではメタ文字ではありません。
$ # create substitute command for each line
$ sed 's/.*/s|"&"|\\L\&|gi/' f1
s|"+stringa +Dog +Cat"|\L&|gi
s|"+cat +Tux +elephant"|\L&|gi
$ # pass those commands as sed script
$ sed -f <(sed 's/.*/s|"&"|\\L\&|gi/' f1) ip.csv
"123456 Abc","+Stringx +123","something"
"23456 dEf","+cat +tux +elephant","Other something"
"34524 xyz","+stringa +dog +cat","third something"
$ # or save them in a file and use
$ sed 's/.*/s|"&"|\\L\&|gi/' f1 > f2
$ sed -f f2 ip.csv
\L
文字列を小文字に変換するg
行内のすべての出現箇所を置換します。i
大文字と小文字を区別しません。
もし持っていないならGNU sed
$ # \Q to quote metacharacters
$ # but will have issues if you have \ or $ or @
$ sed 's/.*/s|\\Q"&"|\\L$\&|gi;/' f1
s|\Q"+stringa +Dog +Cat"|\L$&|gi;
s|\Q"+cat +Tux +elephant"|\L$&|gi;
$ perl -p <(sed 's/.*/s|\\Q"&"|\\L$\&|gi;/' f1) ip.csv
"123456 Abc","+Stringx +123","something"
"23456 dEf","+cat +tux +elephant","Other something"
"34524 xyz","+stringa +dog +cat","third something"
ステファン・シャゼラスが指摘したように、コンテンツがf1
管理されていない場合、コードインジェクションの脆弱性につながる可能性がある。
答え2
ではperl
、それぞれ言葉最初のファイルでは小文字に変換されます:
perl -pe '
BEGIN {local $/ = undef; $regex = join "|", map qr{\Q$_\E}i, split " ", <>}
s/$regex/\L$&/g' file1.words file2.csv
local $/ = undef
は、BEGINブロックのレコードセパレータを未定義にし、<>
そこでの1回の呼び出しで最初のファイル(file1.words
)全体を丸呑みします。それを空白で分割し(ではと同様にsplit " "
が特別です)、結果の単語を で結合します。perl
awk -F " "
awk
|
正規表現引用符付き大文字と小文字を区別しないようにしました。
(?i:word1)|(?i:word2)|...
したがって、2 番目のファイルの残りのコードの各行に適用する、次のような巨大な正規表現があります。
各文字列がライン最初のファイルの場合は、次のように簡略化できます。
perl -pe '
BEGIN {chomp (@strings = <STDIN>); $regex = join "|", map qr{\Q$_\E}i, @strings}
s/$regex/\L$&/g' < file1.strings file2.csv
そこで、最初のファイルを引数として渡す代わりに、stdin で開きます。 は、<STDIN>
で区切り文字を削除しchomp
、|
上記のように で結合した行のリストを返します。
ASCII 文字に制限したくない場合は、-Mopen=locale
オプションを追加します。
答え3
AWK
解決策(現在の入力の場合):
2 番目のフィールドが主な関心事であり、検索ファイル内の値が二重引用符で囲まれていると仮定します。
awk 'NR==FNR{ $0="\042"$0"\042"; a[$0]; next }
$2 in a{ $2=tolower($2) }1' patterns FS=',' OFS=',' file.csv
$0="\042"$0"\042"
- 包むパターンpatterns
ファイルの行を反復処理中に二重引用符で囲まれた行a[$0]
- キャプチャパターン行を配列にa
$2 in a{ $2=tolower($2) }
- ファイルの行の2番目のフィールド値がfile.csv
パターンのリスト(つまり配列a
)にある場合 - その中のすべての文字を小文字に変換します$2=tolower($2)
出力:
"123456 Abc","+Stringx +123","something"
"23456 dEf","+cat +tux +elephant","Other something"
"34524 xyz","+stringa +dog +cat","third something"