Usando awk para somar os valores de uma coluna, com base nos valores de outra coluna

Estou tentando somar certos números em uma coluna usando awk. Eu gostaria de somar apenas a coluna 3 dos “ferreiros” para obter um total de 212. Posso somar a coluna inteira usando awk, mas não apenas os “ferreiros”. Eu tenho:

awk "BEGIN {FS = "|"} ; {sum+=$3} END {print sum}" filename.txt 

Também estou usando massa. Obrigado por qualquer ajuda.

smiths|Login|2 olivert|Login|10 denniss|Payroll|100 smiths|Time|200 smiths|Logout|10 

Resposta

awk -F "|" "$1 ~ /smiths/ {sum += $3} END {print sum}" inputfilename 
  • O sinalizador -F define o separador de campo; Coloquei-o entre aspas simples porque é um caractere especial de shell.
  • Em seguida, $1 ~ /smiths/ aplica o seguinte {bloco de código} apenas às linhas em que o primeiro campo corresponde ao regex /smiths/.
  • O resto é igual ao seu código.

Observe que, como você não está usando um regex aqui, apenas um valor específico, você poderia facilmente use:

awk -F "|" "$1 == "smiths" {sum += $3} END {print sum}" inputfilename 

Que verifica a igualdade da string. Isso é equivalente a usar o regex /^smiths$/, conforme mencionado em outro resposta, que inclui a âncora ^ para corresponder apenas ao início da string (o início do campo 1) e a $ âncora apenas corresponda ao final da string. Não tenho certeza se você está familiarizado com regexes. Elas são muito poderosas, mas, neste caso, você pode usar uma verificação de igualdade de string com a mesma facilidade.

Comentários

  • A propósito, minha referência favorita no awk é grymoire.com/Unix/Awk.html . Página muito útil .
  • Obrigado @Wildcard! Consegui agregar ordenadamente um tamanho descompactado de arquivos específicos em um grande arquivo zip com base em seu conselho 🙂

Resposta

Outra abordagem é usar arrays associativos awk, mais informações aqui . Esta linha produz a saída desejada:

awk -F "|" "{a[$1] += $3} END{print a["smiths"]}" filename.txt 

Como efeito colateral, a matriz armazena todos os outros valores:

awk -F "|" "{a[$1] += $3} END{for (i in a) print i, a[i]}" filename.txt 

Resultado:

smiths 212 denniss 100 olivert 10 

Comentários

  • Esta é a resposta certa

Resposta

Muito bom até agora. Tudo que você precisa fazer é adicionar um seletor antes do bloco para adicionar a soma. Aqui verificamos se o primeiro argumento contém apenas “smiths”:

awk "BEGIN {FS = "|"} ; $1 ~ /^smiths$/ {sum+=$3} END {print sum}" 

Você poderia encurtar isso um pouco especificando o separador de campo como uma opção. Em awk, geralmente é uma boa ideia inicializar variáveis na linha de comando:

awk -F"|" "$1 ~ /^smiths$/ {sum+=$3} END {print sum}" 

Resposta

Pessoalmente, prefiro manter a seção awk o mais simples possível e fazer o máximo que puder sem ela . A lógica combinada não tira proveito do poder dos pipelines Unix e, portanto, é mais difícil de entender, depurar ou modificar para casos de uso intimamente relacionados.

cat filename.txt | perl -pe "s{.*|}{}g" | awk "{sum+=$1} END {print sum}" 

Resposta

cat filename.txt | grep smiths | awk -F "|" "{sum+=$NF} END {print sum}" 
  • -F opção para especificar o separador .
  • $NF é para “última coluna”.

Comentários

  • cat e grep são desnecessários aqui.
  • Por que o grep é desnecessário @Andrey? OP deseja adicionar apenas " smiths " linhas. Você ' d precisa modificar a instrução awk, certo?
  • @EL sim, a instrução awk deve ser modificada para /smiths/{...} se a chamada grep não estiver lá. Esta é uma modificação trivial, mas oferece benefícios significativos: diminui o número de processos em execução, simplifica o controle de erros e torna o código mais claro.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *