Como substituir vírgulas entre parênteses

2

Eu tenho um arquivo de texto com a seguinte aparência:

12.com,128.15.8.6,TEXT1,no1,['128.15.8.6']
23com,122.14.10.7,TEXT2,no2,['122.14.10.7']
45.com,91.33.10.4,TEXT3,no3,['91.33.10.4']
67.com,88.22.88.8,TEXT4,no4,['88.22.88.8', '5.112.1.10']

Como eu quero inserir o conteúdo do arquivo em uma tabela usando o comando MySQL, dizer separated by ',', a cadeia lat entre os colchetes (que pode conter strings separadas por vírgula) está causando problemas onde o MySQL quer separá-los, mas a tabela não tem colunas suficientes para eles.

Eu quero substituir as vírgulas entre os colchetes [] por semicolon ; .

Como posso fazer isso no Linux de uma maneira simples?

EDIT # 1

O número de strings separadas por , dentro dos colchetes não está definido. Pode ser 1, 2, 3, etc. Eu preciso substituir , sempre que encontrar dentro de colchetes com ; .

    
por user9371654 12.08.2018 / 11:25

5 respostas

0

sed também pode funcionar:

sed 'h; s/.*[[]/[/; s/,/;/g; x; s/[[].*//; G; s/\n// ' file

Explicação:

sed '   h;          save the entire line to hold space 
        s/.*[[]/[/  remove anything till the opening '['
        s/,/;/g     replace ALL commas with semicolons
        x           save modified bracketed text, get back original line 
        s/[[].*//   get rid of the bracketed text
        G           append the modified text
        s/\n//      remove the <newline> char introduced by 'G'
 ' file
    
por 12.08.2018 / 11:50
1

Como as strings nos colchetes são sempre prefixadas por uma aspa simples, você pode simplesmente substituir o par assim:

$ sed "s/',/';/g" file
12.com,128.15.8.6,TEXT1,no1,['128.15.8.6']
23com,122.14.10.7,TEXT2,no2,['122.14.10.7']
45.com,91.33.10.4,TEXT3,no3,['91.33.10.4']
67.com,88.22.88.8,TEXT4,no4,['88.22.88.8'; '5.112.1.10']
67.com,88.22.88.8,TEXT4,no4,['88.22.88.8'; '5.112.1.10'; '1.2.3.4']
67.com,88.22.88.8,TEXT4,no4,['88.22.88.8'; '5.112.1.10'; '1.2.3.4'; '2.3.4.5']

Alternativa que lida com 3 ou menos

Para substrings dentro dos colchetes de até 3 de comprimento ( ['xxx', 'yyy', 'zzz'] ). Você pode usar sed para fazer isso:

$ sed 's/\([^\[]*\)\([^,]*\),\([^,]*\)/;/g' file
12.com,128.15.8.6,TEXT1,no1;['128.15.8.6']
23com,122.14.10.7,TEXT2,no2;['122.14.10.7']
45.com,91.33.10.4,TEXT3,no3;['91.33.10.4']
67.com,88.22.88.8,TEXT4,no4,['88.22.88.8'; '5.112.1.10']
67.com,88.22.88.8,TEXT4,no4,['88.22.88.8'; '5.112.1.10'; '1.2.3.4']

Como funciona

Dentro dessa solução, há uma pesquisa simples & substitua s/.../.../g

  • s/\([^\[]*\) - corresponde tudo ao [ (zero ou mais) e o salva em
  • \([^,]*\) - corresponde tudo ao , e o salva em
  • , - corresponde a uma vírgula
  • \([^,]*\) - corresponde a tudo que não é uma vírgula e salva em
  • /;/g - reconstrói os bits de forma que é ; agora, avidamente
por 12.08.2018 / 11:49
0

Se é o último campo e o número de colunas é fixo, você pode usar o bash:

while IFS=, read v1 v2 v3 v4 rest; do
    echo "$v1,$v2,$v3,$v4,${rest//,/;}"
done

Resultado:

12.com,128.15.8.6,TEXT1,no1,['128.15.8.6']
23com,122.14.10.7,TEXT2,no2,['122.14.10.7']
45.com,91.33.10.4,TEXT3,no3,['91.33.10.4']
67.com,88.22.88.8,TEXT4,no4,['88.22.88.8'; '5.112.1.10']

Você pode colocar as declarações acima em um arquivo (junto com #!/bin/bash no topo) e alimentar seu arquivo como stdin para esse script, ou você pode nomear o arquivo no script:

while IFS=, read v1 v2 v3 v4 rest; do
    echo "$v1,$v2,$v3,$v4,${rest//,/;}"
done < yourfile

Isso usa IFS para dividir a linha no , . os quatro primeiros campos são atribuídos a v1..v4, enquanto tudo depois disso é atribuído à última variável, aqui chamado rest . O eco, em seguida, envia as variáveis separadas por , , enquanto na última variável é substituído por ; .

    
por 12.08.2018 / 11:32
0

Supondo que não haja aninhados [...] :

sed -e :1 -e 's/\(\[[^]]*\),/;/g' -e t1 < file.in > file.out
    
por 12.08.2018 / 13:03
0

o awk é bem legal aqui: use o colchete aberto como separador de campo e substitua todas as vírgulas no 2º campo.

awk 'BEGIN {FS = OFS = "["} {gsub(/,/, ";", $2)} 1' file
    
por 13.08.2018 / 15:42