Séparateur d'échappement entre guillemets, en awk

j'utilise awk pour analyser mes données avec", " comme séparateur car l'entrée est un fichier csv. Cependant, il y a "," dans les données qui s'est échappé par des guillemets ("...").

exemple

filed1,filed2,field3,"field4,FOO,BAR",field5

Comment puis-je ignorer la virgule "," dans les le double devis afin que je puisse analyser les données en sortie correctement à l'aide de awk? Je sais que nous pouvons le faire dans excel, mais comment nous le faisons dans awk?

26
demandé sur smci 2011-10-18 12:52:27

3 réponses

c'est facile, avec GNU awk 4 :

zsh-4.3.12[t]% awk '{ 
 for (i = 0; ++i <= NF;)
   printf "field %d => %s\n", i, $i
 }' FPAT='([^,]+)|("[^"]+")' infile
field 1 => filed1
field 2 => filed2
field 3 => field3
field 4 => "field4,FOO,BAR"
field 5 => field5

ajout de quelques commentaires selon L'exigence de L'OP.

De la GNU awk manuel :

la valeur de FPAT devrait être une chaîne qui fournit une expression. Cette expression régulière décrit le contenu de chaque champ. Dans le cas des données CSV présentées ci-dessus, chaque champ est soit "tout ce qui est pas une virgule", ou "une double citation, quelque chose de ce n'est pas une double citation, et une double citation finale."S'il est écrit que une constante d'expression régulière (voir Chapitre 3 [Expressions régulières], page 37), nous aurions /([^,]+)|("[^"]+")/. Ecrire ceci sous forme de chaîne nous oblige à échapper aux doubles guillemets, conduisant à: FPAT = "([^,]+)|(\"[^\"]+\")"

21
répondu Dimitre Radoulov 2011-10-19 09:48:56

FPAT fonctionne quand il y a des lignes et des virgules à l'intérieur des champs cités, mais pas quand il y a des guillemets doubles, comme ceci:

field1,"field,2","but this field has ""escaped"" quotes"

vous pouvez utiliser un programme d'enrubannage simple que j'ai écrit appelé csvquote pour rendre les données faciles à interpréter par awk, puis restaurer les caractères spéciaux problématiques, comme ceci:

csvquote inputfile.csv | awk -F, '{print }' | csvquote -u

voir https://github.com/dbro/csvquote pour code et docs

11
répondu D Bro 2013-05-04 23:49:33

parseurs CSV à part entière tels que Perl Text::CSV_XS sont conçus pour gérer ce genre de bizarrerie.

supposons que vous voulez seulement imprimer le 4ème champ:

perl -MText::CSV_XS -lne 'BEGIN{$csv=Text::CSV_XS->new()} if($csv->parse($_)){ @f=$csv->fields(); print "\"$f[3]\"" }' file

la ligne d'entrée est divisée en tableau @f

La zone 4 est $f[3] puisque Perl commence l'indexation à 0

j'ai fourni plus d'explication de Text::CSV_XS dans ma réponse ici: analyse fichier csv utilisant gawk

1
répondu Chris Koknat 2017-05-23 12:18:03