Substituindo aspas em um arquivo

0

Eu tenho um grande número de arquivos de dados separados por ponto-e-vírgula grande. Todos os campos de string estão entre aspas duplas. Em alguns dos arquivos, há citações extras nos campos de string, o que atrapalha a importação subseqüente dos dados para análise (estou importando para o Stata).

Este código permite-me ver as citações problemáticas usando o gnu-awk:

echo '"This";"is";1;"line" of" data";""with";"extra quotes""' | awk 'BEGIN { FPAT = "([^;]+)|(\"[^\"]+\")"}; {for ( i=1 ; i<=NF ; i++ ) if ($i ~ /^"(.*".*)+"$/) {print NR, $i}}'
1 "line" of" data"
1 ""with"
1 "extra quotes""

mas não sei como substituí-los.

Eu estava pensando em fazer a substituição manualmente, mas acontece que há centenas de correspondências em alguns dos arquivos. Eu sei sobre as funções -sub-, -gsub- e -match- do awk, mas não tenho certeza de como projetar uma pesquisa e substituir esse problema específico.

No exemplo acima, os respectivos campos devem ser "This" , "is" , 1 , "line of data" , "with" , "extra quotes" , ou seja: todos os ponto-e-vírgulas são separadores e todas as citações, exceto as cotas mais externas devem ser removidas.

Devo ser usado com o mesmo nome ou ser a ferramenta certa? Espero que você possa me ajudar!

Obrigado,

Matthijs

    
por Matthijs 09.10.2012 / 09:10

3 respostas

1

Minha própria solução, usando apenas sed , removendo todos os pontos-e-vírgulas que não são justapostos com delimitadores ou campos numéricos (o comando awk está lá apenas para clareza de exposição):

echo '"This";"is";1;"line" of" data";""without";"extra quotes""' | sed -E 's/([^;])"+([^;])//g' | awk 'BEGIN { FPAT = "([^;]+)|(\"[^\"]+\")"}; {for ( i=1 ; i<=NF ; i++ ) print $i}'
"This"
"is"
1
"line of data"
"without"
"extra quotes"

Acho que é mais rápido, pois funciona nas linhas completas em vez de dividir a linha nos campos.

    
por 10.10.2012 / 11:31
1

Uma maneira de usar GNU awk e FPAT :

awk 'BEGIN { FPAT = "([^;]+)|(\"[^\"]+\")" } { for (i=1; i<=NF; i++) if (substr($i,0,1) == "\"" && substr($i,length($i),1) == "\"") { gsub(/"/, "", $i); printf "\"%s\"\n", $i } else { gsub(/"/, "", $i); print $i } }'

Teste:

echo '"This";"is";1;"line" of" data";""with";"extra quotes""' | awk 'BEGIN { FPAT = "([^;]+)|(\"[^\"]+\")" } { for (i=1; i<=NF; i++) if (substr($i,0,1) == "\"" && substr($i,length($i),1) == "\"") { gsub(/"/, "", $i); printf "\"%s\"\n", $i } else { gsub(/"/, "", $i); print $i } }'

Resultados:

"This"
"is"
1
"line of data"
"with"
"extra quotes"

Uma maneira de usar GNU awk , FPAT e GNU sed :

sed -e '/^".*"$/ { s/"//g; s/.*/"&"/ }' -e '/^".*"$/!s/"//g'

Teste:

echo '"This";"is";1;"line" of" data";""with";"extra quotes""' | awk 'BEGIN { FPAT = "([^;]+)|(\"[^\"]+\")" } { for (i=1; i<=NF; i++) print $i }' | sed -e '/^".*"$/ { s/"//g; s/.*/"&"/ }' -e '/^".*"$/!s/"//g'

Resultados:

"This"
"is"
1
"line of data"
"with"
"extra quotes"
    
por 09.10.2012 / 14:48
1

Eu preferiria usar o coreutils e o sed (versões GNU):

<<< '"This";"is";1;"line" of" data";""with";"extra quotes""' \
| tr ';' '\n' | sed -r 's/(.)"(.)//g' | tr '\n' ';'

Saída:

"This";"is";1;"line of data";"with";"extra quotes";

Ele deixa um ponto-e-vírgula extra e descarta a nova linha, insere head -c -1 antes da segunda tr e acrescenta ; echo para corrigir:

tr ';' '\n' | sed -r 's/(.)"(.)//g' | head -c -1 | tr '\n' ';'; echo

Saída:

"This";"is";1;"line of data";"with";"extra quotes"
    
por 09.10.2012 / 22:37

Tags