我有兩個文件,一個文件包含字串列表。
+stringa +Dog +Cat
+cat +Tux +elephant
第二個檔案 (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
正如 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)|...
我們在程式碼的其餘部分中應用到第二個檔案的每一行的東西。
如果是每個字串中的每個線第一個文件的,那麼可以簡化為:
perl -pe '
BEGIN {chomp (@strings = <STDIN>); $regex = join "|", map qr{\Q$_\E}i, @strings}
s/$regex/\L$&/g' < file1.strings file2.csv
在那裡,我們在標準輸入上打開第一個文件,而不是將其作為參數傳遞。<STDIN>
返回其行的列表,我們從中刪除分隔符號chomp
, 並按上面的方式連接|
。
如果您不希望限制為 ASCII 字符,請新增該-Mopen=locale
選項。
答案3
AWK
解決方案(針對您目前的輸入):
假設第二個欄位是主要關注點,並且搜尋文件中的值用雙引號引起來。
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) }
- 如果檔案行的第二個欄位值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"