Noções básicas sobre arquivos AWK e CSV

Oct 20 2020

Como posso escrever um programa AWK que analisa uma lista de campos em arquivos CSV, contar o número de cada string diferente no campo especificado e imprimir a contagem de cada string que for encontrada? Eu só codifiquei em C e Java, então estou completamente confuso sobre a sintaxe do AWK. Eu entendo o mais simples dos conceitos, no entanto, AWK é estruturado de maneira muito diferente. Qualquer hora é apreciada, obrigado!

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]
}

Em um arquivo CSV contendo:

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

Consigo obter o 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 é o resultado desejado:

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

Há uma edição em meu código que foi comentada.

Respostas

1 JamesBrown Oct 21 2020 at 03:35

Corrigido seu 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

Saída (usando GNU awk. Outros awks exibiram a saída em ordem diferente):

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 não é a ferramenta certa para este trabalho. Embora AWK possa interpretar dados separados por vírgula ou tabulação, ele não tem nenhum conceito de delimitação de campo ou escape. Portanto, ele poderia lidar com um exemplo simples como:

Month,Day
January,Sunday
February,Monday

mas falharia com este exemplo válido:

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

Por causa disso, eu recomendaria considerar outro 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

Ou Ruby:

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

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

Ou mesmo 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