web-dev-qa-db-fra.com

Utilisation de awk pour additionner les valeurs d'une colonne, en fonction des valeurs d'une autre colonne

J'essaie de additionner certains nombres dans une colonne en utilisant awk. Je voudrais additionner juste la colonne 3 des "forgerons" pour obtenir un total de 212. Je peux additionner la colonne entière en utilisant awk mais pas seulement les "forgerons". J'ai:

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

J'utilise aussi PuTTY. Merci pour toute aide.

smiths|Login|2
olivert|Login|10
denniss|Payroll|100
smiths|Time|200
smiths|Logout|10
75
jake
awk -F '|' '$1 ~ /smiths/ {sum += $3} END {print sum}' inputfilename
  • Le -F flag définit le séparateur de champ; Je l'ai mis entre guillemets simples car il s'agit d'un caractère Shell spécial.
  • Alors $1 ~ /smiths/ applique le {bloc de code} suivant uniquement aux lignes où le premier champ correspond à l'expression régulière /smiths/.
  • Le reste est le même que votre code.

Notez que puisque vous n'utilisez pas vraiment une expression régulière ici, juste une valeur spécifique, vous pouvez tout aussi facilement utiliser:

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

Qui vérifie l'égalité des chaînes. Cela équivaut à utiliser l'expression régulière /^smiths$/, comme mentionné dans une autre réponse, qui comprend le ^ ancre pour faire correspondre uniquement le début de la chaîne (le début du champ 1) et le $ ancre pour correspondre uniquement à la fin de la chaîne. Je ne sais pas dans quelle mesure vous connaissez les expressions rationnelles. Ils sont très puissants, mais dans ce cas, vous pouvez utiliser une vérification d'égalité de chaîne tout aussi facilement.

95
Wildcard

Une autre approche consiste à utiliser des tableaux associatifs awk, plus d'infos ici . Cette ligne produit la sortie souhaitée:

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

Comme effet secondaire, le tableau stocke toutes les autres valeurs:

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

Production:

smiths 212
denniss 100
olivert 10
19
Andrey

Très bien jusqu'ici. Tout ce que vous avez à faire est d'ajouter un sélecteur avant le bloc pour ajouter la somme. Ici, nous vérifions que le premier argument ne contient que des "forgerons":

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

Vous pouvez raccourcir cela un peu en spécifiant le séparateur de champs en option. Dans awk c'est généralement une bonne idée d'initialiser des variables sur la ligne de commande:

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

Personnellement, je préférerais garder la section awk aussi simple que possible et en faire autant que possible sans elle. La logique mixte ne tire pas parti de la puissance des pipelines Unix et est donc plus difficile à comprendre, à déboguer ou à modifier pour des cas d'utilisation étroitement liés.

cat filename.txt | Perl -pe 's{.*|}{}g' | awk '{sum+=$1} END {print sum}'
1
Sridhar Sarnobat
cat filename.txt | grep smiths | awk -F '|' '{sum+=$NF} END {print sum}'
  • -F option pour spécifier le séparateur.
  • $NF est pour la "dernière colonne".
0
forzagreen