Tente:
awk -F "|" '{ a[$5]+=1+length($0) } END{for (name in a) print name,a[name]}' trace.log
Exemplo
Vamos considerar este arquivo de teste:
$ cat trace.log
1|2|3|4|jerry|6
a|b|c|d|phil|f
1|2|3|4|jerry|6
O comando original produz esta saída:
$ awk -F "|" '{ print $5 }' trace.log | sort | uniq | xargs -l sh -c 'echo -n $0 && grep "$0" trace.log | wc -c'
jerry32
phil15
O comando sugerido, que percorre o arquivo apenas uma vez, produz esta saída:
$ awk -F "|" '{ a[$5]+=1+length($0) } END{for (name in a) print name,a[name]}' trace.log
jerry 32
phil 15
Como funciona
-
-F "|"
Isso define o separador de campo para entrada.
-
a[$5]+=1+length($0)
Para cada linha, adicionamos o comprimento da linha à contagem armazenada na matriz associativa
a
no nome de usuário desta linha.A quantidade
length($0)
não inclui a nova linha que termina a linha. Consequentemente, adicionamos um a isso para contabilizar o\n
. -
END{for (name in a) print name,a[name]}
Depois de lermos o arquivo uma vez, imprimimos as somas.