¿Encuentra líneas duplicadas en un archivo y cuenta cuántas veces se duplicó cada línea?


529

Supongamos que tengo un archivo similar al siguiente:

123 
123 
234 
234 
123 
345

Me gustaría saber cuántas veces se ha duplicado '123', cuántas veces se ha duplicado '234', etc. Así que, idealmente, el resultado sería:

123  3 
234  2 
345  1

44
¿Qué idioma quieres usar?
VMAtm

Respuestas:


791

Suponiendo que haya un número por línea:

sort <file> | uniq -c

También puede usar el --countindicador más detallado con la versión GNU, por ejemplo, en Linux:

sort <file> | uniq --count

3
Esto es lo que hago, pero algorítmicamente este no parece ser el enfoque más eficiente (O (n log n) * avg_line_len donde n es el número de líneas). Estoy trabajando en archivos de varios gigabytes, por lo que el rendimiento es un problema clave. Me pregunto si hay una herramienta que solo cuente en una sola pasada usando un árbol de prefijos (en mi caso, las cadenas a menudo tienen prefijos comunes) o similar, eso debería ser el truco en O (n) * avg_line_len. ¿Alguien sabe una herramienta de línea de comandos?
Droggl

21
Un paso adicional es canalizar la salida de eso en un comando final 'sort -n'. Eso ordenará los resultados por los cuales las líneas ocurren con mayor frecuencia.
samoz

79
Si solo desea imprimir líneas duplicadas, use 'uniq -d'
DmitrySandalov

66
Si desea ordenar nuevamente el resultado, puede usarlo sortnuevamente como:sort <file> | uniq -c | sort -n
Abhishek Kashyap

414

Esto imprimirá solo líneas duplicadas , con recuentos:

sort FILE | uniq -cd

o, con las opciones largas de GNU (en Linux):

sort FILE | uniq --count --repeated

en BSD y OSX debe usar grep para filtrar líneas únicas:

sort FILE | uniq -c | grep -v '^ *1 '

Para el ejemplo dado, el resultado sería:

  3 123
  2 234

Si desea imprimir recuentos para todas las líneas, incluidas las que aparecen solo una vez:

sort FILE | uniq -c

o, con las opciones largas de GNU (en Linux):

sort FILE | uniq --count

Para la entrada dada, la salida es:

  3 123
  2 234
  1 345

Para ordenar la salida con las líneas más frecuentes en la parte superior, puede hacer lo siguiente (para obtener todos los resultados):

sort FILE | uniq -c | sort -nr

o, para obtener solo líneas duplicadas, las más frecuentes primero:

sort FILE | uniq -cd | sort -nr

en OSX y BSD el último se convierte en:

sort FILE | uniq -c | grep -v '^ *1 ' | sort -nr

1
Buen punto con la opción --repetido o -d. ¡Mucho más preciso que usar "| grep 2" o similar!
Lauri

¿Cómo puedo modificar este comando para recuperar todas las líneas cuyo recuento de repetición es superior a 100?
Black_Rider

@Black_Rider Agregar | sort -no | sort -nra la tubería ordenará la salida por recuento de repeticiones (ascendente o descendente, respectivamente). Esto no es lo que estás preguntando, pero pensé que podría ayudar.
Andrea

1
@Black_Rider awk parece capaz de hacer todo tipo de cálculos: en su caso, podría hacerlo| awk '$1>100'
Andrea

44
@fionbio Parece que no puedes usar -c y -d juntos en OSX uniq . Gracias por señalarlo. Puede usar grep para filtrar líneas únicas :sort FILE | uniq -c | grep -v '^ *1 '
Andrea

72

Para buscar y contar líneas duplicadas en varios archivos, puede probar el siguiente comando:

sort <files> | uniq -c | sort -nr

o:

cat <files> | sort | uniq -c | sort -nr

30

Vía :

awk '{dups[$1]++} END{for (num in dups) {print num,dups[num]}}' data

En awk 'dups[$1]++'comando, la variable $1contiene todo el contenido de la columna 1 y los corchetes son acceso a la matriz. Entonces, para cada 1ra columna de línea en el dataarchivo, el nodo de la matriz nombrada dupsse incrementa.

Y al final, estamos recorriendo una dupsmatriz con una numvariable e imprimimos primero los números guardados y luego su número de valores duplicados dups[num].

Tenga en cuenta que su archivo de entrada tiene espacios al final de algunas líneas, si las borra, puede usarlas $0en lugar del $1comando anterior :)


1
¿No es esto un poco exagerado teniendo en cuenta que tenemos uniq?
Nathan Fellman

99
sort | uniqy la solución awk tiene compensaciones de rendimiento y recursos bastante diferentes: si los archivos son grandes y el número de líneas diferentes es pequeño, la solución awk es mucho más eficiente. Es lineal en el número de líneas y el uso del espacio es lineal en el número de líneas diferentes. OTOH, la solución awk necesita mantener todas las diferentes líneas en la memoria, mientras que la clasificación (GNU) puede recurrir a archivos temporales.
Lars Noschinski

14

En Windows usando "Windows PowerShell" usé el comando mencionado a continuación para lograr esto

Get-Content .\file.txt | Group-Object | Select Name, Count

También podemos usar el cmdlet where-object para filtrar el resultado

Get-Content .\file.txt | Group-Object | Where-Object { $_.Count -gt 1 } | Select Name, Count

¿Puedes eliminar todas las apariciones de los duplicados, excepto el último ... sin cambiar el orden de clasificación del archivo?
jparram

6

Suponiendo que tiene acceso a un entorno estándar de shell y / o cygwin de Unix:

tr -s ' ' '\n' < yourfile | sort | uniq -d -c
       ^--space char

Básicamente: convierta todos los caracteres de espacio en saltos de línea, luego ordene la salida traducida y aliméntela a uniq y cuente las líneas duplicadas.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.