Comprensión de archivos AWK y CSV

Oct 20 2020

¿Cómo puedo escribir un programa AWK que analice una lista de campos en archivos CSV, cuente el número de cada cadena diferente en el campo especificado e imprima el recuento de cada cadena que se encuentra? Solo he codificado en C y Java, por lo que estoy completamente confundido con la sintaxis de AWK. Entiendo los conceptos más simples, sin embargo, AWK está estructurado de manera muy diferente. Cualquier momento es apreciado, ¡gracias!

BEGIN {
    FS = ""
}
{
    for(i = 1; i <= NF; i++) 
        freq[$i]++
    PROCINFO ["sorted_in"] = "@val_num_desc" #this got the desired result
}
END {
    for {this in freq) 
        printf "%s\t%d\n", this, freq[this]
}

En un archivo CSV que contiene:

Field1, Field2, Field3, Field4
A, B, C, D
A, E, F, G
Z, E, C, D
Z, W, C, Q

Puedo obtener el resultado:

A     2
B     1
C     3
Q     1
D     1
E     2
F     1
,     12
G     1
W     1
Field1,Field2,Field3,Field4     1
Z     2

Este es el resultado deseado:

A       10
C       7
D       2
E       2
Z       2
B       1
Q       1
Field1  1
Field2  1
F       1
Field3  1
G       1
Field4  1
W       1

Hay una edición en mi código que está comentada.

Respuestas

1 JamesBrown Oct 21 2020 at 03:35

Corregido tu código:

$ awk ' BEGIN { # you need BEGIN block for FS FS = ", *" # your data had ", " and "," seps } # ... based on your sample output { for(i = 1; i <= NF; i++) freq[$i]++
}
END {
    for(this in freq)                       # fixed a parenthesis
        printf "%s\t%d\n", this, freq[this]
}' file

Salida (usando GNU awk. Otros awks muestran la salida en diferente orden):

A       2
B       1
C       3
Q       1
D       2
Field1  1
E       2
Field2  1
F       1
Field3  1
G       1
Field4  1
W       1
Z       2
StevenPenny Oct 21 2020 at 03:10

AWK realmente no es la herramienta adecuada para este trabajo. Si bien AWK puede interpretar datos separados por comas o tabulaciones, no tiene el concepto de recintos de campo o escapes. Entonces podría manejar un ejemplo simple como:

Month,Day
January,Sunday
February,Monday

pero fallaría con este ejemplo válido:

Month,Day
January,"Sunday"
February,"Monday"

Por eso, recomendaría considerar otro idioma. Algo como Python:

import csv
o = open('a.csv')
for m in csv.DictReader(o):
   print(m)

https://docs.python.org/library/csv.html

O Ruby:

require 'csv'
CSV.table('a.csv').each do |m|
   p m
end

https://ruby-doc.org/stdlib/libdoc/csv/rdoc/CSV.html

O incluso PHP:

<?php
$r = fopen('a.csv', 'r'); $a_head = fgetcsv($r); while (true) { $a_row = fgetcsv($r); if (feof($r)) {
      break;
   }
   $m_row = array_combine($a_head, $a_row); print_r($m_row);
}

https://php.net/function.fgetcsv