Como substituir espaço simples ou duplo em um arquivo de texto entre aspas

2

Eu tenho um arquivo CSV com alguns campos citados, mas as entradas entre aspas são separadas por espaços duplos ou simples. Eu preciso que estes sejam substituídos por vírgulas.

Exemplo de linha:

This is okay,"ABC DEF GHI",123,"This is not okay",remove,spaces,within,quotes

E como deve ser:

This is okay,"ABC,DEF,GHI",123,"This,is,not,okay",remove,spaces,within,quotes

    
por TomNash 01.08.2016 / 19:47

3 respostas

2

perl -pe 's/".*?"/do{$a = $&; $a =~ s: +:,:g; $a}/ge;'

Essencialmente, este é apenas um substituto de regex global s/regex/replacement/g . A regex é ".*?" , corresponde a todas as subseqüências que começam com " e termina com a próxima sequência " . As partes complicadas são:

  • A substituição não é uma string, mas uma expressão que é avaliada. (Esse é o significado do modificador e após g .)
  • A expressão que é avaliada é novamente um substituto de regex global s:regex:replacement:g que substitui qualquer sequência não vazia de espaços por uma vírgula. (Não podemos usar o mesmo delimitador como na substituição externa, por isso usamos : em vez de / .)
  • Para executar a substituição do regex interno, temos que atribuir a subsequência correspondente do substituto externo $& a outra variável $a , executar a substituição interna em $a e, finalmente, imprimir $a .

Com uma versão perl suficientemente recente, a atribuição a uma variável auxiliar pode ser evitada. Usando o modificador r , a substituição interna pode ser executada diretamente em uma cópia da substring combinada $& (graças a Stéphane Chazelas):

perl -pe 's/".*?"/$&=~s: +:,:gr/ge;'
    
por 02.08.2016 / 17:17
1

Considere esta solução awk de força bruta:

awk -F, -v OFS=, '
  {
    for(i=1;i<=NF;i++)
        if ($i ~ /^".*"$/)
                gsub(" +", ",", $i)
    print $0
  }'

Ele diz ao awk para dividir os registros em vírgulas - observando que isso irá quebrar se algum dos seus campos contiver uma vírgula! - e usando o OFS para dizer a instrução print para recombinar os campos com vírgulas. O loop for passa por cada campo da linha e, se o campo iniciar ^ com aspas duplas, tem os caracteres .* e termina $ com aspas duplas, então substitua globalmente nessa $i field qualquer número de espaços com vírgulas. Depois de passar pelos campos, imprima o registro inteiro ( $0 ).

    
por 01.08.2016 / 21:18
1

Com o GNU awk :

gawk -v RS=\" '
  NR % 2 == 0{gsub(/ +/, ",")}
  {ORS = RT; print}'

Ou seja, o separador de registro é feito com o caractere " e os espaços em branco são substituídos apenas em registros pares.

RT é a parte específica do GNU.

Mesmo com o GNU sed :

tr '\n"' '"\n' | sed -E '2~2s/ +/,/g' | tr '"\n' '\n"'

Mais portably:

tr '\n"' '"\n' | sed 'n;s/  */,/g' | tr '"\n' '\n"'

funcionaria com outros sed s, embora você possa ter problemas se o último caractere da entrada não for um " .

    
por 02.08.2016 / 17:30