Vérifier que toutes les lignes d'un fichier sont uniques


11

J'ai un fichier texte contenant des lignes comme celle-ci:

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

Comment puis-je être sûr de l'unicité de chaque ligne?

REMARQUE: le but est de tester le fichier et non de le modifier si des lignes en double sont présentes.



1
Voulez-vous vérifier si toutes les lignes sont uniques ou souhaitez-vous supprimer les doublons?
8bittree

1
@ 8bittree - je veux juste être sûr de l'unicité
snr

Réponses:


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

Exactement ce que j'aurais dit, sauf avec uniqau lieu desort -u
Nonny Moose

1
Si l'entrée n'est pas déjà triée, ce uniqserait une grosse erreur; il déduplique uniquement les lignes adjacentes!
alexis

1
Si l'on s'intéresse aux coupables, un sort <file> | uniq -dimprimerait les doublons.
Rolf

25

Solution awk:

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

4
+1 La réponse acceptée lit deux fois l'intégralité du fichier, tandis que celle-ci s'arrête dès qu'elle rencontre une ligne en double en une lecture. Cela fonctionnera également avec l'entrée canalisée, tandis que les autres ont besoin de fichiers qu'il peut relire.
JoL

Vous ne pourriez pas pousser le echodans END?
Ignacio Vazquez-Abrams

2
@ IgnacioVazquez-Abrams Il n'y a vraiment aucun intérêt dans l'écho. Faire && echoou || echoest une convention dans les réponses pour indiquer qu'une commande fait la bonne chose avec le code d'état de sortie. L'important est le exit(1). Idéalement, vous utiliseriez cela comme if has_only_unique_lines file; then ..., non if [[ $(has_only_unique_lines file) = "no dupes" ]]; then ..., ce serait idiot.
JoL

2
Lorsque d'autres réponses lisent le fichier deux fois pour économiser de la mémoire, cela lira le fichier entier en mémoire, s'il n'y a pas de dupes.
Kusalananda

1
@Kusalananda Bien que cela lise tout le fichier en mémoire lorsqu'il n'y a pas de dupes, l'utilisation de la sortvolonté aussi, qu'il y ait ou non des dupes, n'est-ce pas? Comment est-ce que cela économise de la mémoire?
JoL

21

Utilisation de sort/ uniq:

sort input.txt | uniq

Pour vérifier uniquement les lignes en double, utilisez l' -doption pour uniq. Cela ne montrera que les lignes qui sont en double, sinon aucune ne montrera rien:

sort input.txt | uniq -d

Ceci est mon goto. Je ne sais pas ce que les autres réponses plus votées offrent que celle-ci ne le fait pas.
user1717828

1
C'est une bonne alternative pour supprimer les doublons.
snr

1
Cela ne fait pas ce qu'il veut. Il veut savoir s'il y a des doublons, pas les supprimer.
Barmar

@Barmar: Bien que cela semble être le cas, la question n'est toujours pas claire. Ainsi que les PO commentent pour tenter de le clarifier.
jesse_b

Une modification en attente ajoute des précisions.
Barmar

5

TLDR

La question initiale n'était pas claire et indiquait que le PO voulait simplement une version unique du contenu d'un fichier. C'est indiqué ci-dessous. Dans la forme mise à jour de la question depuis, le PO déclare maintenant qu'il / elle veut simplement savoir si le contenu du fichier est unique ou non.


Tester si le contenu du fichier est unique ou non

Vous pouvez simplement utiliser sortpour vérifier si un fichier est unique ou contient des doublons comme ceci:

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

Exemple

Disons que j'ai ces deux fichiers:

fichier d'exemple en double
$ 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
fichier d'exemple unique
$  cat uniq_input.txt
A
B
C
D

Maintenant, lorsque nous analysons ces fichiers, nous pouvons dire s'ils sont uniques ou contiennent des doublons:

tester le fichier de doublons
$ sort -uC dup_input.txt && echo "unique" || echo "duplicates"
duplicates
tester un fichier unique
$ sort -uC uniq_input.txt && echo "unique" || echo "duplicates"
unique

Question d'origine (contenu unique du fichier)

Peut être fait avec juste 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

J'utilise généralement sortle fichier, puis j'utilise uniqpour compter le nombre de doublons, puis je sortrevois les doublons en bas de la liste.

J'ai ajouté un double aux exemples que vous avez fournis:

$ 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

Comme je n'ai pas lu la page de manuel depuis uniqun moment, j'ai jeté un coup d'œil à toutes les alternatives. Ce qui suit élimine le besoin du deuxième tri, si vous voulez juste voir les doublons:

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

C'est une bonne alternative en effet. #rez
snr

2

S'il n'y a pas de doublons, toutes les lignes sont uniques:

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

Description: Triez les lignes du fichier pour rendre les lignes répétées consécutives (tri)
Extrayez toutes les lignes consécutives qui sont égales (uniq -d).
S'il y a une sortie de la commande ci-dessus ( [...]), ( &&) imprime un message.


2

Cela ne serait pas complet sans une réponse Perl!

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

Cela imprimera une fois chaque ligne non unique: donc s'il n'imprime rien, alors le fichier a toutes les lignes uniques.


1

Utilisation cmpet sortdans bash:

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

ou

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

Cela trierait cependant le fichier deux fois, tout comme la réponse acceptée.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.