Eu gosto de espaços em branco e nomes de variáveis descritivas. O que mais há a dizer? Já faz um tempo desde que eu escrevi muito awk
, eu até me esqueci do -f
no shebang. No entanto, como eu fiz isso eu realmente senti como se estivesse no zen dele. código do Haiku.
Eu gosto dessa solução porque há um mínimo de lógica codificada. Apenas dois loops for iterando sobre índices de array. Nenhum passo de 3 partes for
loops, nenhuma declaração de if
, nenhuma comparação explícita de valor. Todas essas coisas estão estatisticamente correlacionadas a defeitos de software (bugs). Curiosamente, não há atribuições explícitas, e apenas uma operação matemática, o incremento na contagem. Acho que isso tudo indica o uso máximo dos recursos do idioma.
Sinto que algo pode estar faltando, mas ainda não consegui encontrar nenhum furo.
Por favor, comente. Opiniões e críticas construtivas solicitadas. Gostaria de saber sobre as considerações de desempenho desse script.
#!/usr/bin/awk -f
function count(seen, unique_count) {
for (ij in seen) {
split(ij, fields, SUBSEP)
++unique_count[fields[1]]
}
}
{
seen2[$1,$2]
seen3[$1,$3]
}
END {
count(seen2, count2)
count(seen3, count3)
for (i in count3) {
print i, count2[i], count3[i]
}
}
Anotação
Eu acho que um recurso exclusivo desse script é que as matrizes seen2
e seen3
não contêm dados, apenas índices. Isso é porque estamos contando apenas valores únicos, portanto, a única coisa que importa é que os valores foram vistos, não nos importamos com quantas vezes eles ocorrem.
#!/usr/bin/awk -f
A função count
usa uma matriz, seen
, indexada por dois valores de campo encontrados nos registros de entrada, campos 1 e 2 ou campos 1 e 3 e retorna uma matriz internamente chamada unique_count
indexada pelo primeiro campo, contendo as contagens de valores de campo exclusivos para a coluna acumulada pelo segundo índice:
function count(seen, unique_count) {
A função count
itera sobre os índices da matriz seen
:
for (ij in seen) {
Divide o índice nos dois valores originais, campo 1 e campo 2 ou campo 3:
split(ij, fields, SUBSEP)
Incrementar a contagem do elemento indexado pelo campo 1:
++unique_count[fields[1]]
}
}
Em cada linha de entrada encontrada, criamos um elemento de matriz vazio, se já não existir, indexado pelo primeiro campo e o segundo ou terceiro campo. Mantenha uma matriz separada ( seen2
e seen3
) para cada número de campo que está sendo contado. Haverá apenas um elemento de matriz para cada valor único na coluna especificada (2 ou 3):
{
seen2[$1,$2]
seen3[$1,$3]
}
No final dos dados, conte o número de campos exclusivos vistos para cada coluna:
END {
Transmita os arrays acumulados da entrada para a função count
e receba o count2
ou count3
preenchido com as contagens de campo exclusivas.
count(seen2, count2)
count(seen3, count3)
Passe por um dos arrays count2
ou count3
(não importa qual é o primeiro campo de cada linha) e imprima o campo um, seguido pelas contagens de valores exclusivos encontrados para cada linha contendo o campo um:
for (i in count3) {
print i, count2[i], count3[i]
}
}
Versão de um liner
awk 'function c(s,u){for(x in s){split(x,f,SUBSEP); ++u[f[1]];}}
{a[$1,$2]; b[$1,$3];} END {c(a,d); c(b,e); for(i in d){print i,d[i],e[i];}}'