Comment utiliser awk pour extraire un champ entre guillemets?

j’utilise

awk '{ printf "%s", $3 }' 

pour extraire un champ d’une ligne délimitée par un espace. Bien sûr, je reçois des résultats partiels lorsque le champ est cité avec des espaces libres à l’intérieur. Un organisme peut-il suggérer une solution s’il vous plaît?

C’est en fait assez difficile. Je suis venu avec le script awk suivant qui divise la ligne manuellement et stocke tous les champs dans un tableau.

 { s = $0 i = 0 split("", a) while ((m = match(s, /"[^"]*"/)) > 0) { # Add all unquoted fields before this field n = split(substr(s, 1, m - 1), t) for (j = 1; j <= n; j++) a[++i] = t[j] # Add this quoted field a[++i] = substr(s, RSTART + 1, RLENGTH - 2) s = substr(s, RSTART + RLENGTH) if (i >= 3) # We can stop once we have field 3 break } # Process the remaining unquoted fields after the last quoted field n = split(s, t) for (j = 1; j <= n; j++) a[++i] = t[j] print a[3] } 

affichez votre fichier d’entrée et la sortie souhaitée la prochaine fois. Pour obtenir des champs cotés,

 $ cat file field1 field2 "field 3" field4 "field5" $ awk -F'"' '{for(i=2;i<=NF;i+=2) print $i}' file field 3 field5 

Voici une solution alternative possible à ce problème. Il fonctionne en trouvant les champs qui commencent ou se terminent par des guillemets, puis en les joignant. A la fin, il met à jour les champs et NF, donc si vous mettez plus de patterns après celui qui fait la fusion, vous pouvez traiter les (nouveaux) champs en utilisant toutes les fonctionnalités awk normales.

Je pense que cela utilise uniquement les fonctionnalités de POSIX awk et ne repose pas sur les extensions gawk, mais je ne suis pas tout à fait sûr.

 # This function joins the fields $start to $stop together with FS, shifting # subsequent fields down and updating NF. # function merge_fields(start, stop) { #printf "Merge fields $%d to $%d\n", start, stop; if (start >= stop) return; merged = ""; for (i = start; i <= stop; i++) { if (merged) merged = merged OFS $i; else merged = $i; } $start = merged; offs = stop - start; for (i = start + 1; i <= NF; i++) { #printf "$%d = $%d\n", i, i+offs; $i = $(i + offs); } NF -= offs; } # Merge quoted fields together. { start = stop = 0; for (i = 1; i <= NF; i++) { if (match($i, /^"/)) start = i; if (match($i, /"$/)) stop = i; if (start && stop && stop > start) { merge_fields(start, stop); # Start again from the beginning. i = 0; start = stop = 0; } } } # This rule executes after the one above. It sees the fields after merging. { for (i = 1; i <= NF; i++) { printf "Field %d: >>>%s<<<\n", i, $i; } } 

Sur un fichier d'entrée comme:

 thing "more things" "thing" "more things and stuff" 

cela produit:

 Field 1: >>>thing<<< Field 2: >>>"more things"<<< Field 3: >>>"thing"<<< Field 4: >>>"more things and stuff"<<< 

Si vous cherchez simplement un domaine spécifique, alors

 $ cat file field1 field2 "field 3" field4 "field5" awk -F"\"" '{print $2}' file 

travaux. Il divise le fichier par “, donc le deuxième champ de l’exemple ci-dessus est celui que vous voulez.