Sprawdź, czy wszystkie wiersze pliku są unikalne

11

Mam plik tekstowy zawierający takie linie:

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

Jak mogę być pewien wyjątkowości każdej linii?

UWAGA: Celem jest przetestowanie pliku, a nie modyfikowanie go, jeśli występują zduplikowane linie.

snr
źródło
1
Łączenie w: unix.stackexchange.com/q/76049/117549
Jeff Schaller
1
Czy chcesz sprawdzić, czy wszystkie linie są unikalne, czy chcesz usunąć duplikaty?
8bittree,
1
@ 8bittree - chcę mieć pewność, że wyjątkowość
snr

Odpowiedzi:

24
[ "$(wc -l < input)" -eq "$(sort -u input | wc -l)" ] && echo all unique
Jeff Schaller
źródło
Dokładnie to, co powiedziałbym, z wyjątkiem uniqzamiastsort -u
Nonny Moose
1
Jeśli dane wejściowe nie są jeszcze posortowane, uniqbyłby to duży błąd; deduplikuje tylko sąsiednie linie!
Alexis
1
Jeśli ktoś jest zainteresowany sprawcami, sort <file> | uniq -dwydrukuje duplikaty.
Rolf,
25

Rozwiązanie awk:

awk 'a[$0]++{print "dupes"; exit(1)}' file && echo "no dupes"
iruvar
źródło
4
+1 Zaakceptowana odpowiedź czyta cały plik dwa razy, a zatrzymuje się, gdy tylko napotka podwójną linię w jednym odczycie. Będzie to również działać z wejściem potokowym, podczas gdy inne pliki wymagają ponownego odczytania.
JoL
Nie mogłeś wpakować się echoINTO END?
Ignacio Vazquez-Abrams,
2
@ IgnacioVazquez-Abrams Naprawdę nie ma sensu echo. Wykonanie && echolub || echojest konwencją w odpowiedziach, wskazującą, że polecenie działa poprawnie z kodem statusu wyjścia. Ważną rzeczą jest exit(1). Idealnie byłoby użyć tego tak if has_only_unique_lines file; then ..., jakby nie if [[ $(has_only_unique_lines file) = "no dupes" ]]; then ..., to byłoby głupie.
JoL
2
Tam, gdzie inne odpowiedzi odczytują plik dwa razy, aby zaoszczędzić pamięć, spowoduje to odczytanie całego pliku do pamięci, jeśli nie będzie duplikatów.
Kusalananda
1
@Kusalananda Chociaż spowoduje to wczytanie całego pliku do pamięci, gdy nie będzie żadnych duplikatów, użycie sortbędzie również, niezależnie od tego, czy są duplikaty, czy nie, prawda? Jak to oszczędza pamięć?
JoL
21

Używanie sort/ uniq:

sort input.txt | uniq

Aby sprawdzić tylko zduplikowane linie, użyj -dopcji uniq. Spowoduje to wyświetlenie tylko zduplikowanych wierszy, jeśli nie, nic nie pokaże:

sort input.txt | uniq -d
jesse_b
źródło
To jest moje goto. Nie jestem pewien, co oferują inne, wyżej głosowane odpowiedzi, których nie ma.
user1717828,
1
To dobra alternatywa dla usuwania duplikatów.
snr
1
To nie robi tego, czego chce. Chce wiedzieć, czy są duplikaty, a nie usuwać je.
Barmar
@Barmar: Choć wydaje się, że w ten sposób pytanie wciąż jest niejasne. Jak również komentarze OP próbujące to wyjaśnić.
jesse_b,
Oczekuje na edycję, która dodaje więcej wyjaśnień.
Barmar
5

TLDR

Pierwotne pytanie było niejasne i czytano, że OP chciał po prostu unikalnej wersji zawartości pliku. To pokazano poniżej. W zaktualizowanej formie pytania OP twierdzi teraz, że po prostu chce wiedzieć, czy zawartość pliku jest unikalna, czy nie.


Sprawdź, czy zawartość pliku jest unikalna, czy nie

Możesz po prostu użyć sortdo sprawdzenia, czy plik jest unikalny lub zawiera takie duplikaty:

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

Przykład

Powiedz, że mam te dwa pliki:

zduplikowany plik przykładowy
$ 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
unikalny przykładowy plik
$  cat uniq_input.txt
A
B
C
D

Teraz, gdy analizujemy te pliki, możemy stwierdzić, czy są one unikalne, czy zawierają duplikaty:

test duplikatów pliku
$ sort -uC dup_input.txt && echo "unique" || echo "duplicates"
duplicates
przetestuj unikalny plik
$ sort -uC uniq_input.txt && echo "unique" || echo "duplicates"
unique

Oryginalne pytanie (unikalna zawartość pliku)

Można to zrobić za pomocą 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
slm
źródło
3

Zwykle sortplik, następnie używam uniqdo zliczania liczby duplikatów, a następnie sortznów widzę duplikaty na dole listy.

Dodałem jeden duplikat do podanych przykładów:

$ 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

Ponieważ uniqod jakiegoś czasu nie czytałem strony podręcznika, szybko szukałem alternatyw. Poniższe eliminuje potrzebę drugiego sortowania, jeśli chcesz zobaczyć tylko duplikaty:

$ sort thread.file | uniq -d
This is a thread  139737505302272
Carlos Hanson
źródło
To naprawdę dobra alternatywa. #rez
snr
2

Jeśli nie ma duplikatów, wszystkie wiersze są unikalne:

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

Opis: posortuj wiersze pliku, aby powtarzały się kolejne wiersze (sortuj)
Wyodrębnij wszystkie kolejne wiersze, które są równe (uniq -d).
Jeśli istnieje wynik wyjściowy polecenia powyżej ( [...]), a następnie ( &&) wydrukuj komunikat.

Izaak
źródło
2

Nie byłoby to kompletne bez odpowiedzi Perla!

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

Spowoduje to wydrukowanie każdej nieunikalnej linii jeden raz: jeśli więc nic nie wydrukuje, to plik ma wszystkie unikalne linie.

frapadingue
źródło
1

Korzystanie cmpi sortw bash:

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

lub

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

Spowodowałoby to jednak sortowanie pliku dwa razy, podobnie jak zaakceptowana odpowiedź.

Kusalananda
źródło