web-dev-qa-db-fra.com

Utiliser awk pour compter le nombre d'occurrences d'un mot dans une colonne

03/03/2014 12:31:21 BLOCK 10.1.34.1 11:22:33:44:55:66

03/03/2014 12:31:22 ALLOW 10.1.34.2 AA:BB:CC:DD:EE:FF

03/03/2014 12:31:25 BLOCK 10.1.34.1 55:66:77:88:99:AA

J'essaie d'utiliser awk pour compter le nombre d'occurrences du mot "bloc" et "accès" ci-dessus dans une seule commande.

J'ai essayé le mot "bloc" au début mais mon compteur ne semble pas fonctionner. Quelqu'un peut-il voir où mon code est erroné?

awk ' BEGIN {count=0;}  { if ($3 == "BLOCK") count+=1} end {print $count}' firewall.log
13
user3578872

Utilisez un tableau

awk '{count[$3]++} END {for (Word in count) print Word, count[Word]}' file

Si vous voulez spécifiquement "bloquer": END {print count["BLOCK"]}

30
glenn jackman

Voici une solution non codée. Vous pouvez enchaîner les étapes avec des tuyaux ("|").

awk '{print $3}' file | sort | uniq -c
  • awk '{print $ 3}'
    imprimez la 3ème colonne, le séparateur d'enregistrement par défaut dans awk est un espace blanc.

  • trier
    triez les résultats

  • uniq -c
    compter le nombre d'occurrences répétées

15
David Thornton

La raison pour laquelle votre code ne fonctionne pas est END est sensible à la casse donc votre script vérifiera la variable end existe (ce qui n'est pas le cas) et donc le dernier bloc ne sera jamais exécuté . Si vous changez cela, cela devrait fonctionner.

De plus, vous n'avez pas besoin du bloc BEGIN car toutes les variables sont instanciées à 0.

Ci-dessous, j'ai ajouté une autre façon de le faire que vous pouvez utiliser à la place.

Ceci est similaire à glenn mais ne capture que les mots que vous voulez, il devrait utiliser peu de mémoire à cause de cela.


Utiliser Gawk (pour le troisième argument du match)

awk 'match($3,/BLOCK|ALLOW/,b){a[b[0]]++}END{for(i in a)print i ,a[i]}' file

Ce bloc ne s'exécute que si BLOCK ou ALLOW sont contenus dans le troisième champ.
La correspondance capture ce qui a été mis en correspondance dans le tableau b.
Ensuite, le tableau a est incrémenté pour le champ correspondant.

Dans le bloc END, chaque champ capturé est sorti avec un nombre d'occurrences.


La sortie est

ALLOW 1
BLOCK 2
4
user4453924

J'ai testé ta déclaration

awk ' BEGIN {count=0;}  { if ($3 == "BLOCK") count+=1} end {print $count}' firewall.log

et a réussi à compter BLOCK en effectuant deux modifications

  1. end doit être en majuscules
  2. retirer $ de print $count

Donc, ça devrait être:

awk ' BEGIN {count=0;}  { if ($3 == "BLOCK") count+=1} END {print count}' firewall.log 

Une déclaration plus simple qui fonctionne aussi est la suivante:

awk '($3 == "BLOCK") {count++ } END { print count }' firewall.log
3
psoo

L'erreur dans votre appel awk est que, dans votre bloc "END", vous avez print $count. Cela prend le contenu de la variable count, suppose qu'il s'agit d'un entier et tente de trouver le champ correspondant dans la dernière ligne d'entrée. Ce que vous voulez vraiment, c'est simplement print count, car cela affiche simplement la valeur dans la variable count. Il est parfois facile de mélanger différents schémas de référencement de variables entre bash, awk, python, etc., c'est donc une erreur facile à faire.

1
twalberg