Alterar uma lista de strings para minúsculas

Alterar uma lista de strings para minúsculas

Eu tenho dois arquivos, um arquivo contém uma lista de strings.

+stringa +Dog +Cat
+cat +Tux +elephant

e o segundo arquivo (csv) contém algo como:

"123456 Abc","+Stringx +123","something"
"23456 dEf","+cat +Tux +elephant","Other something"
"34524 xyz","+stringa +Dog +Cat","third something"

o resultado deve ser:

"123456 Abc","+Stringx +123","something"
"23456 dEf","+cat +tux +elephant","Other something"
"34524 xyz","+stringa +dog +cat","third something"

Como posso alterar as strings que correspondem à minha lista de padrões para minúsculas?

Meu arquivo de valores separados por vírgula tem cerca de 30 colunas e cerca de 1.500 linhas.

Responder1

Com GNU sed, assume que você não possui nenhum metacaractere na lista de strings, +não é um metacaractere com BRE padrão

$ # 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 
  • \Lpara converter string em minúsculas
  • gpara substituir todas as ocorrências em uma linha, ipara correspondência sem distinção entre maiúsculas e minúsculas


Se você não temGNU 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"


Conforme observado por Stéphane Chazelas, isso pode levar a vulnerabilidades de injeção de código se o conteúdo f1não estiver sob controle

Responder2

Com perl, supondo que você queira cadapalavrano primeiro arquivo a ser colocado em letras minúsculas:

perl -pe '
 BEGIN {local $/ = undef; $regex = join "|", map qr{\Q$_\E}i, split " ", <>}
 s/$regex/\L$&/g' file1.words file2.csv

local $/ = undeftorna o separador de registro para o bloco BEGIN indefinido, de modo que aquela invocação <>dele, sorve todo o primeiro arquivo ( file1.words). Dividimos isso em espaço em branco ( split " "é especial in perlda mesma forma que awk -F " "está em awk) e juntamos as palavras resultantes com |depois de tercitado em regexe os tornou insensíveis a maiúsculas e minúsculas.

Portanto, temos um regexp enorme que é algo parecido (?i:word1)|(?i:word2)|...com o que aplicamos em cada linha do segundo arquivo no restante do código.

Se for cada string em cadalinhado primeiro arquivo, então isso pode ser simplificado para:

perl -pe '
 BEGIN {chomp (@strings = <STDIN>); $regex = join "|", map qr{\Q$_\E}i, @strings}
 s/$regex/\L$&/g' < file1.strings file2.csv

Lá, abrimos o primeiro arquivo no stdin em vez de passá-lo como argumento. <STDIN>retorna uma lista de suas linhas das quais removemos os delimitadores com chompe juntamos |como acima.

Se você não quiser que seja limitado a caracteres ASCII, adicione a -Mopen=localeopção.

Responder3

AWKsolução (para sua entrada atual):

Supondo que o segundo campo seja de interesse principal e os valores no arquivo de pesquisa estejam entre aspas.

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"- embrulhe umpadrãolinha com aspas duplas enquanto itera pelas linhas do patternsarquivo

  • a[$0]- capturando umpadrãolinha em arraya

  • $2 in a{ $2=tolower($2) }- se o valor do segundo campo da linha do file.csvarquivo estiver na lista de padrões (ou seja, array a) - converta todos os caracteres nele para letras minúsculas$2=tolower($2)


A saída:

"123456 Abc","+Stringx +123","something"
"23456 dEf","+cat +tux +elephant","Other something"
"34524 xyz","+stringa +dog +cat","third something"

informação relacionada