将字符串列表更改为小写

将字符串列表更改为小写

我有两个文件,一个文件包含字符串列表。

+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 " "),并将结果单词与在拥有以后perlawk -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"

相关内容