Altera uma lista de cadeias para minúsculas

2

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 1500 linhas.

    
por FaxMax 27.11.2017 / 11:24

3 respostas

3

Com GNU sed , assume que você não tem nenhum meta caractere na lista de strings, + não é um meta caractere com o padrão 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 para converter uma string em minúscula
  • g para substituir todas as ocorrências em uma linha, i para correspondência sem distinção entre maiúsculas e minúsculas


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


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

    
por 27.11.2017 / 12:02
2

Com perl , supondo que você queira que cada palavra no primeiro arquivo seja convertido em minúsculas:

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

local $/ = undef torna o separador de registro para o bloco BEGIN indefinido, de modo que a única invocação de <> , devora todo o primeiro arquivo ( file1.words ). Dividimos isso no espaço em branco ( split " " é especial em perl da mesma forma que awk -F " " está em awk ), e junte as palavras resultantes com | depois de tê-las regex-citado e as insense.

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

Se for cada string em cada linha do primeiro arquivo, 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 em stdin em vez de passá-lo como argumento. <STDIN> retorna uma lista de suas linhas das quais removemos os delimitadores com chomp e associamos com | como acima.

Se você não quer que ele seja limitado a caracteres ASCII, adicione a opção -Mopen=locale .

    
por 27.11.2017 / 12:14
2
Solução

AWK (para sua entrada atual):

Supondo que o segundo campo é de interesse principal e os valores no arquivo de pesquisa são citados com aspas duplas.

awk 'NR==FNR{ $0="2"$0"2"; a[$0]; next }
     $2 in a{ $2=tolower($2) }1' patterns FS=',' OFS=',' file.csv
  • $0="2"$0"2" - envolva uma linha padrão com aspas duplas enquanto percorre as linhas de patterns file

  • a[$0] - capturando uma linha padrão no array a

  • $2 in a{ $2=tolower($2) } - se o 2º valor do campo da linha do arquivo file.csv estiver na lista de padrões (isto é, matriz a ) - converter todos os caracteres para% min_$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"
    
por 27.11.2017 / 11:50