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
egrep
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.