Compter le nombre de fois où chaque adresse IP apparaît dans le fichier journal

9

J'ai un fichier au format suivant:

$ cat file.txt

27.33.65.2
27.33.65.2
58.161.137.7
121.50.198.5
184.173.187.1
184.173.187.1
184.173.187.1

Quelle est la meilleure façon d'analyser le fichier file.txtdans un format comme:

27.33.65.2: 2
58.161.137.7: 1
121.50.198.5: 1
184.173.187.1: 3

En d'autres termes, je veux parcourir le fichier et compter le nombre de fois que chaque adresse IP apparaît. Je l'ai déjà parcouru, sortdonc toutes les adresses IP sont en ordre et directement les unes après les autres.

James Spittal
la source
Personnellement, j'importerais ce type de fichier dans une base de données à proximité pratique (en créant une table temporaire dans n'importe quelle instance postgres que j'ai), suivie d'une action SQL rapide et de l'exporter vers un fichier texte.
oakad

Réponses:

23

Vous cherchez uniq -c

Si le résultat n'est pas à votre goût, il peut être analysé et reformaté facilement.

Par exemple:

$ uniq -c logfile.txt | awk '{print $2": "$1}'
27.33.65.2: 2
58.161.137.7: 1
121.50.198.5: 1
184.173.187.1: 3
glenn jackman
la source
Combiner uniqet awkne semble pas être une excellente approche pour moi ...
Hauke ​​Laging
3
Parce uniqque ne fonctionne que sur les entrées triées (il correspond aux lignes correspondantes adjacentes, pas aux lignes du fichier).
oakad
1
Vous devez trier les résultats avant de les rediriger vers uniq. Si vous lisez le Q original, l'OP indique qu'il a déjà trié les résultats en utilisant sort!
slm
2
@HaukeLaging - J'apprécie ce que vous dites, mais de la même manière que la plupart des utilisateurs d'ordinateurs ne s'aventureront jamais au-delà d'OSX et de Windows, de plus, la plupart des utilisateurs d'Unix ne s'aventureront pas au-delà de l'utilisation d'outils désignés pour des tâches spécifiques. L'utilisation d'AWK n'est pas pour les âmes sensibles, regardez ce que vous aviez à faire pour effectuer cette tâche de base en utilisant AWK par rapport à ce que la solution de Glenn exigeait. Je pense que je suis juste en disant que c'est une solution plus simple à saisir mentalement, bien que la vôtre soit probablement plus efficace. BTW, j'ai fait des UV tous les deux car ils sont tous les deux corrects!
slm
1
@HaukeLaging - Oui, exactement. Lorsque vous vous promenez sur le site, nos responsabilités changent légèrement, OMI. Nous sommes chargés de créer des A'ers complets et de regarder les A'ers que nous fournissons comme moments d'enseignement au PO et à chaque futur visiteur qui le rencontre, encore une fois l'OMI. Mais c'est un choix personnel, donc si vous n'avez que quelques minutes à perdre, fournir un A sous n'importe quelle forme est toujours apprécié.
slm
6

uniqsemble être la solution la plus intelligente, en effet. La manière awk:

awk '{ip_count[$0]++}; '\
'END {for (ip in ip_count) printf "%15s: %d\n",ip,ip_count[ip];}' file
Hauke ​​Laging
la source
+1. Si l'ordre de sortie est important pour l'OP, cette réponse ne donne aucune garantie: l'itération sur les clés d'un tableau associatif n'a pas d'ordre inhérent.
glenn jackman
@glennjackman Mais ajouter sortà ma réponse est encore plus rapide car moins d'articles doivent être triés. ;-)
Hauke ​​Laging
Oh oui? OH OUI?!? ;) l'entrée est déjà triée. Cette réponse awk les mélange, donc c'est encore plus de travail. Nyah! ;)
glenn jackman
0

le fichier de tri firest obtient alors le compte par unic -c

sort filename | uniq -c

Aeyd Moeyd
la source
1
Le fichier est déjà trié (selon l'utilisateur dans la question) et uniq -cfonctionnerait mais fournirait la sortie au mauvais format. C'est pourquoi la réponse acceptée n'utilise pas sortet reformate à la place la sortie de uniq -c.
Kusalananda
Merci @Aeyd. Je cherchais cette commande. Cela aide
user11392987
0

J'utiliserais python. Chaque ststem linux a de nos jours installé python2.

Ajoutez chaque adresse IP dans un dict (tableau associatif) sous forme de paires clé = valeur, c'est-à-dire {"12.34.56.78": 1, "87.76.43.21": 3}.

Vous "vérifiez" l'adresse IP en tant que clé et incrémentez la valeur de 1. Si vous utilisez defaultdict ("ip"), si la clé n'existe pas, elle est créée avec une valeur par défaut de 0. Si la clé existe déjà, defaultdict ne fait rien. La valeur est incrémentée sur la ligne suivante.

#!/usr/bin/python2

infile = open("file.txt","r")
iplist = {}  # create an empty dict

for line in infile:
    line = line.strip()   # remove newline.
    if line: # if not a blank line.
        iplist.setdefault(line, 0) # check for ip and add with default value of 0
        iplist[line] += 1 # increment

outfile = open("out.txt","w") #open output file

for key in iplist.keys():
    line = "%-15s = %s" % (key, iplist[key])
    print line   # print uf desired.
    outfile.write(line + "\n")

fichier outout:

cat out.txt                                                          
27.33.65.2      = 2
58.161.137.7    = 1
121.50.198.5    = 1
184.173.187.1   = 3

Je sais que vous cherchiez une solution de ligne de commande, mais comme vous pouvez le voir, c'est un affichage au format élégant qui ne prenait qu'une douzaine de lignes environ. Python est un excellent outil d'administration.

Mike Childers
la source