Trier et compter le nombre d'occurrences de lignes

145

J'ai Apachelogfile, access.logcomment compter le nombre d'occurrence de ligne dans ce fichier? par exemple le résultat de cut -f 7 -d ' ' | cut -d '?' -f 1 | tr '[:upper:]' '[:lower:]'is

a.php
b.php
a.php
c.php
d.php
b.php
a.php

le résultat que je veux est:

3 a.php
2 b.php
1 d.php # order doesn't matter
1 c.php 
Kokizzu
la source
25
| sort | uniq -c
Costas
3
| LC_ALL=C sort | LC_ALL=C uniq -c
Stéphane Chazelas
ah je ne sais jamais qui uniqpourrait faire ça ..
Kokizzu
Avez-vous un exemple de la ligne dans le journal, car je pense que tout cela pourrait être fait avec awk sans tous les tuyaux.
c'est bon, fichier journal de 8,1 Go traité en 2 minutes environ, et c'est fait pour le moment, vous n'en
avez

Réponses:

197
| sort | uniq -c

Comme indiqué dans les commentaires.

Piping the output en sortorganise la sortie en ordre alphabétique / numérique.

Ceci est une exigence car les uniqcorrespondances uniquement sur des lignes répétées, c'est-à-dire

a
b
a

Si vous utilisez uniqsur ce fichier texte, il retournera ce qui suit:

a
b
a

C'est parce que les deux as sont séparés par le b- ils ne sont pas des lignes consécutives. Cependant, si vous triez d'abord les données dans l'ordre alphabétique, comme

a
a
b

Puis uniqsupprimera les lignes répétitives. L' -coption de uniqcompte le nombre de doublons et fournit une sortie sous la forme:

2 a
1 b

Références:

visudo
la source
1
Bienvenue dans Unix et Linux :) N'hésitez pas à ajouter plus de détails à votre réponse et à expliquer pourquoi et comment cela fonctionne;)
John WH Smith
1
printf '%s\n' ①.php ②.php | sort | uniq -cme donne2 ①.php
Stéphane Chazelas
@ StéphaneChazelas C'est parce que les impressions printfphp\nphp
4
@Jidder, non, c'est parce que les triages sont ①.phples mêmes que ②.phpdans mes paramètres régionaux, car aucun ordre de tri n'est défini pour ceux-ci et le caractère dans mes paramètres régionaux. Si vous voulez uniques valeurs pour toutes les valeurs d'octet (souvenez - vous des chemins de fichiers ne sont pas nécessairement du texte), alors vous devez corriger les paramètres régionaux C: | LC_ALL=C sort | LC_ALL=C uniq -c.
Stéphane Chazelas
2
Afin de trier le fichier de comptage résultant, vous devriez envisager d'ajouter le "sort-nr" en tant que réponses @ eduard-florinescu ci-dessous.
Lluís Suñol
104
[your command] | sort | uniq -c | sort -nr

La réponse acceptée est presque terminée, vous pouvez ajouter un petit plus sort -nrà la fin pour trier les résultats avec les lignes qui apparaissent le plus souvent en premier.

options uniq :

-c, --count
       prefix lines by the number of occurrences

options de tri :

-n, --numeric-sort
       compare according to string numerical value
-r, --reverse
       reverse the result of comparisons

Dans le cas particulier où les lignes que vous triez sont des nombres, vous devez les utiliser sort -grau lieu de sort -nr, voir le commentaire

Eduard Florinescu
la source
3
Merci beaucoup de me faire savoir à propos de l' -noption.
Sigur
2
Grande réponse, voici ce que j'utilise pour obtenir un wordcount de fichier avec des phrases: tr ' ' '\n' < $FILE | sort | uniq -c | sort -nr > wordcount.txt. La première commande remplace les espaces par des nouvelles lignes, permettant ainsi au reste de la commande de fonctionner comme prévu.
Bar
2
En utilisant les options ci-dessus, je reçois "1" avant "23344". Utiliser à la sort -grplace résout ce problème. -g: compare en fonction de la valeur numérique générale (au lieu de -n: compare en fonction de la valeur numérique de la chaîne).
Peter Jaric
@PeterJaric Excellente prise et très utile à connaître, -grmais je pense que le résultat de uniq -csera tel sort -nr
quel
3
En fait, lorsque les données sont des nombres, cela -grfonctionne mieux. Essayez ces deux exemples, ne différant que par les drapeaux g et n: echo "1 11 1 2" | tr ' ' '\n' | sort | uniq -c | sort -nret echo "1 11 1 2" | tr ' ' '\n' | sort | uniq -c | sort -gr. Le premier trie de manière incorrecte, mais pas le second.
Peter Jaric
9

Vous pouvez utiliser un tableau associatif sur awk puis, éventuellement, trier :

cat access.log  | awk ' { tot[$0]++ } END { for (i in tot) print tot[i],i } ' | sort

sortie:

1 c.php
1 d.php
2 b.php
3 a.php
Laurence R. Ugalde
la source
Comment comptez-vous le nombre d'occurrences pendant que le canal envoie des données?
user123456