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
文字列リストにデフォルトのBREメタ文字以外にGNU sed
メタ文字が含まれていないとします。+
$ # 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
大文字と小文字を区別せずに一致するように、1行のすべての項目を置き換えるために使用されます。
持っていない場合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
Stéphane Chazelasが指摘したように、コンテンツが制御されていないと、コード挿入の脆弱性が発生する可能性があります。
答え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ブロックのレコード区切り文字を未定義のままにして、単一の呼び出しで最初の<>
ファイル(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>
区切り文字を削除しchomp
、上記のように連結した行のリストを返します|
。
-Mopen=locale
ASCII文字に制限されない場合は、このオプションを追加してください。
答え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]
- 1つをキャプチャ模様行を配列に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"