Noções básicas sobre arquivos AWK e CSV
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
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
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