Czy istnieje jakieś lepsze rozwiązanie do drukowania unikatowych linii inne niż kombinacja sort
i uniq
?
command-line
text-processing
Zostaw mnie w spokoju
źródło
źródło
sort
(np. GNU coreutils) używają plików tymczasowych i zewnętrznego scalania, jeśli dane wejściowe są zbyt duże, aby zmieścić się w pamięci RAM. I większość innych wersji ma-m
opcję, więc można to zrobić jawnie, dzieląc dane wejściowe (np. Za pomocąsplit
), sortując każdy fragment, a następnie łącząc fragmentyOdpowiedzi:
Aby wydrukować każdy identyczny wiersz tylko jeden, w dowolnej kolejności:
Aby wydrukować tylko unikalne linie, w dowolnej kolejności:
Aby wydrukować każdą identyczną linię tylko raz, w kolejności ich pierwszego wystąpienia: (dla każdej linii wydrukuj linię, jeśli jeszcze nie była widoczna, to w każdym razie zwiększ licznik widoczności)
Aby wydrukować tylko unikalne wiersze, w kolejności ich pierwszego wystąpienia: (zapisz każdą linię
seen
, a takżelines
jeśli jest to pierwsze wystąpienie; na końcu danych wejściowych wydrukuj linie w kolejności występowania, ale tylko te widoczne tylko pewnego razu)źródło
awk '!seen[$0]++ {print}'
?awk '!seen[$0]++'
, ponieważ{print}
implikuje to puste polecenie.Niektóre (większość?) Wersje
sort
mają-u
flagę, która wykonujeuniq
część bezpośrednio. Może to być pewne ograniczenia długości linii w zależności od implementacji, ale masz już te z prostymsort|uniq
.źródło
sort -u
wraca co najmniej do V7.-u
ale mają również ograniczenie długości linii do 512 znaków. (Właściwie myślę, że gdzieś w okolicach Solaris 9 Sun podniosło go do 5120. GNU wciąż wygrywa.)Czy Perl działa dla ciebie? Może zachować wiersze w oryginalnej kolejności, nawet jeśli duplikaty nie sąsiadują ze sobą. Możesz go również zakodować w Pythonie lub
awk
.Które można skrócić do sprawiedliwego
Podany plik wejściowy:
Daje to wynik:
źródło
use strict;
aniuse warnings;
(a właściwie jeststrict
to najbardziej istotne w tym przypadku), nie ma żadnych skarg dotyczących używania%lines
przed jego zdefiniowaniem. Jeśli biegniesz z ograniczeniami,my %lines;
przed pętlą musi być linia . Zauważ też, że hash jest%lines
; do jednego elementu skrótu odwołuje się za pomocą$lines{$_}
notacji.sort
rozwiązania mogą być lepsze dla dużej ilości danych (OP był zaniepokojony „przechowywaniem całego pliku w pamięci”).sort
wykona sortowanie poza rdzeniem, jeśli dane są większe niż dostępna pamięć.Dla ostatniej części odpowiedzi wymienionej w: Drukowanie unikalnych linii przez @Gilles jako odpowiedź na to pytanie, starałem się wyeliminować potrzebę używania dwóch skrótów.
To rozwiązanie dotyczy: Aby wydrukować tylko unikalne linie, w kolejności ich pierwszego wystąpienia:
awk '{counter[$0]++} END {for (line in counter) if (counter[line]==1) print line}'
Tutaj „licznik” przechowuje liczbę każdej linii, która jest podobna do tej przetwarzanej wcześniej.
Na koniec drukujemy tylko te linie, które mają wartość licznika jako 1.
źródło