Ordenar y contar el número de ocurrencias de líneas

145

Tengo un Apachearchivo de registro, access.log¿cómo contar el número de ocurrencias de línea en ese archivo? por ejemplo el resultado de cut -f 7 -d ' ' | cut -d '?' -f 1 | tr '[:upper:]' '[:lower:]'es

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

El resultado que quiero es:

3 a.php
2 b.php
1 d.php # order doesn't matter
1 c.php 
Kokizzu
fuente
25
| sort | uniq -c
Costas
3
| LC_ALL=C sort | LC_ALL=C uniq -c
Stéphane Chazelas
ah, nunca sé que uniqpodría hacer eso ..
Kokizzu
¿Tiene un ejemplo de la línea en el registro, ya que creo que todo esto podría hacerse con awk sin todas las tuberías?
está bien, el archivo de registro de 8.1GB se procesó en aproximadamente 2 minutos, y está hecho por ahora, ya no lo necesita más: 3
Kokizzu

Respuestas:

197
| sort | uniq -c

Como se indica en los comentarios.

La canalización de la salida sortorganiza la salida en orden alfabético / numérico.

Este es un requisito porque uniqsolo coincide en líneas repetidas, es decir

a
b
a

Si usa uniqeste archivo de texto, devolverá lo siguiente:

a
b
a

Esto se debe a que las dos as están separadas por b- no son líneas consecutivas. Sin embargo, si primero ordena los datos en orden alfabético primero, como

a
a
b

Luego uniqeliminará las líneas repetidas. La -copción de uniqcuenta el número de duplicados y proporciona resultados en la forma:

2 a
1 b

Referencias

visudo
fuente
1
Bienvenido a Unix y Linux :) No dude en agregar más detalles a su respuesta y explicar por qué y cómo funciona;)
John WH Smith
1
printf '%s\n' ①.php ②.php | sort | uniq -cme da2 ①.php
Stéphane Chazelas
@ StéphaneChazelas Eso es porque imprime printfphp\nphp
44
@Jidder, no, eso se debe a que se ①.phpordena de la misma manera que ②.phpen mi configuración regional porque no se define ningún orden de clasificación para esos y los caracteres en mi configuración regional. Si quieres únicos valores para los valores de bytes (recuerda rutas de archivos no son necesariamente de texto), entonces usted necesita para corregir la configuración regional en C: | LC_ALL=C sort | LC_ALL=C uniq -c.
Stéphane Chazelas
2
Para ordenar el archivo de recuento resultante, debería considerar agregar el "sort -nr" como @ eduard-florinescu responde a continuación.
Lluís Suñol
104
[your command] | sort | uniq -c | sort -nr

La respuesta aceptada está casi completa. Es posible que desee agregar un extra sort -nral final para ordenar los resultados con las líneas que aparecen con mayor frecuencia primero

opciones uniq :

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

opciones de clasificación :

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

En el caso particular, donde las líneas que está ordenando son números, debe usarlas en sort -grlugar de sort -nrver el comentario.

Eduard Florinescu
fuente
3
Muchas gracias por informarme sobre la -nopción.
Sigur
2
Gran respuesta, esto es lo que utilizo para obtener un recuento de palabras de fichero con frases: tr ' ' '\n' < $FILE | sort | uniq -c | sort -nr > wordcount.txt. El primer comando reemplaza los espacios con nuevas líneas, permitiendo que el resto del comando funcione como se esperaba.
Bar
2
Usando las opciones anteriores, obtengo "1" antes de "23344". Usar en su sort -grlugar resuelve esto. -g: compara según el valor numérico general (en lugar de -n: compara según el valor numérico de la cadena).
Peter Jaric
@PeterJaric Gran captura y muy útil para conocer, -grpero creo que el resultado uniq -cserá como tal sort -nry funcionará según lo previsto
Eduard Florinescu
3
En realidad, cuando los datos son números, -grfunciona mejor. Pruebe estos dos ejemplos, que solo difieren en los indicadores gyn: echo "1 11 1 2" | tr ' ' '\n' | sort | uniq -c | sort -nry echo "1 11 1 2" | tr ' ' '\n' | sort | uniq -c | sort -gr. El primero se clasifica incorrectamente, pero no el segundo.
Peter Jaric
9

Puede usar una matriz asociativa en awk y luego -opcionalmente- ordenar :

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

salida:

1 c.php
1 d.php
2 b.php
3 a.php
Laurence R. Ugalde
fuente
¿Cómo contaría el número de ocurrencias a medida que la tubería envía datos?
usuario123456