Verifique que todas las líneas de un archivo sean únicas


11

Tengo un archivo de texto que contiene líneas como esta:

This is a thread  139737522087680
This is a thread  139737513694976
This is a thread  139737505302272
This is a thread  139737312270080
.
.
.
This is a thread  139737203164928
This is a thread  139737194772224
This is a thread  139737186379520

¿Cómo puedo estar seguro de la singularidad de cada línea?

NOTA: El objetivo es probar el archivo, no modificarlo si hay líneas duplicadas.



1
¿Desea verificar si todas las líneas son únicas o desea eliminar cualquier duplicado?
8bittree

1
@ 8bittree - deseo estar seguro de la unicidad
snr

Respuestas:


24
[ "$(wc -l < input)" -eq "$(sort -u input | wc -l)" ] && echo all unique

Exactamente lo que hubiera dicho, excepto con en uniqlugar desort -u
Nonny Moose

1
Si la entrada aún no está ordenada, uniqsería un gran error; ¡solo deduplica las líneas adyacentes!
alexis

1
Si uno está interesado en los culpables, a sort <file> | uniq -dimprimirá los duplicados.
Rolf

25

Awk solución:

awk 'a[$0]++{print "dupes"; exit(1)}' file && echo "no dupes"

44
+1 La respuesta aceptada lee todo el archivo dos veces, mientras que se detiene tan pronto como encuentra una línea duplicada en una lectura. Esto también funcionará con entrada canalizada, mientras que el otro necesita archivos que pueda volver a leer.
JoL

¿No podría empujar el echoen END?
Ignacio Vazquez-Abrams

2
@ IgnacioVazquez-Abrams Realmente no tiene sentido el eco. Hacer && echoo || echoes una convención en las respuestas para indicar que un comando hace lo correcto con el código de estado de salida. Lo importante es el exit(1). Idealmente, usarías esto como if has_only_unique_lines file; then ..., no if [[ $(has_only_unique_lines file) = "no dupes" ]]; then ..., eso sería una tontería.
JoL

2
Donde otras respuestas leen el archivo dos veces para ahorrar memoria, esto leerá todo el archivo en la memoria, si no hay engaños.
Kusalananda

1
@Kusalananda Si bien esto leerá todo el archivo en la memoria cuando no hay engaños, también usará sortwill, independientemente de si hay engaños o no, ¿verdad? ¿Cómo es ese ahorro de memoria?
JoL

21

Usando sort/ uniq:

sort input.txt | uniq

Para verificar solo las líneas duplicadas, use la -dopción para uniq. Esto mostrará solo líneas que están duplicadas, si no mostrará nada:

sort input.txt | uniq -d

Este es mi goto. No estoy seguro de lo que ofrecen las otras respuestas con más votos que esta no.
usuario1717828

1
Es una buena alternativa para eliminar duplicados.
snr

1
Esto no hace lo que quiere. Quiere saber si hay duplicados, no eliminarlos.
Barmar

@Barmar: Si bien parece así, la pregunta aún no está clara. Además de los comentarios de los OP que intentan aclararlo.
jesse_b

Hay una edición pendiente que agrega más aclaraciones.
Barmar

5

TLDR

La pregunta original no estaba clara, y leía que el OP simplemente quería una versión única del contenido de un archivo. Eso se muestra a continuación. En la forma actualizada de la pregunta, el OP ahora declara que simplemente quiere saber si el contenido del archivo es único o no.


Prueba si el contenido del archivo es único o no

Simplemente puede usar sortpara verificar si un archivo es único o contiene duplicados de esta manera:

$ sort -uC input.txt && echo "unique" || echo "duplicates"

Ejemplo

Digamos que tengo estos dos archivos:

archivo de muestra duplicado
$ cat dup_input.txt
This is a thread  139737522087680
This is a thread  139737513694976
This is a thread  139737505302272
This is a thread  139737312270080
This is a thread  139737203164928
This is a thread  139737194772224
This is a thread  139737186379520
archivo de muestra único
$  cat uniq_input.txt
A
B
C
D

Ahora, cuando analizamos estos archivos, podemos saber si son únicos o si contienen duplicados:

prueba de archivos duplicados
$ sort -uC dup_input.txt && echo "unique" || echo "duplicates"
duplicates
prueba de archivo único
$ sort -uC uniq_input.txt && echo "unique" || echo "duplicates"
unique

Pregunta original (contenido único del archivo)

Se puede hacer con solo sort:

$ sort -u input.txt
This is a thread  139737186379520
This is a thread  139737194772224
This is a thread  139737203164928
This is a thread  139737312270080
This is a thread  139737505302272
This is a thread  139737513694976
This is a thread  139737522087680

3

Usualmente sortutilizo el archivo, luego uso uniqpara contar la cantidad de duplicados, luego veo sortuna vez más los duplicados al final de la lista.

Agregué un duplicado a los ejemplos que proporcionó:

$ sort thread.file | uniq -c | sort
      1 This is a thread  139737186379520
      1 This is a thread  139737194772224
      1 This is a thread  139737203164928
      1 This is a thread  139737312270080
      1 This is a thread  139737513694976
      1 This is a thread  139737522087680
      2 This is a thread  139737505302272

Como hace tiempo que no leo la página de manual uniq, busqué rápidamente cualquier alternativa. Lo siguiente elimina la necesidad del segundo tipo, si solo desea ver duplicados:

$ sort thread.file | uniq -d
This is a thread  139737505302272

Es una buena alternativa de hecho. #rez
snr

2

Si no hay duplicados, todas las líneas son únicas:

[ "$(sort file | uniq -d)" ] && echo "some line(s) is(are) repeated"

Descripción: Ordene las líneas del archivo para hacer que las líneas repetidas sean consecutivas (ordenar)
Extraiga todas las líneas consecutivas que sean iguales (uniq -d).
Si hay algún resultado del comando anterior ( [...]), entonces ( &&) imprime un mensaje.


2

¡Esto no estaría completo sin una respuesta de Perl!

$ perl -ne 'print if ++$a{$_} == 2' yourfile

Esto imprimirá cada línea no única una vez: así que si no imprime nada, entonces el archivo tiene todas las líneas únicas.


1

Usando cmpy sorten bash:

cmp -s <( sort file ) <( sort -u file ) && echo 'All lines are unique'

o

if cmp -s <( sort file ) <( sort -u file )
then
    echo 'All lines are unique'
else
    echo 'At least one line is duplicated'
fi

Sin embargo, esto ordenaría el archivo dos veces, al igual que la respuesta aceptada.

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.