Všude, kde vidím někoho, kdo potřebuje získat seřazený, jedinečný seznam, vždy se přesměruje na sort | uniq
. Nikdy jsem neviděl žádné příklady, kdy by někdo místo toho používal sort -u
. Proč ne? Jaký je rozdíl a proč je pro řazení lepší použít uniq než jedinečný příznak?
Komentáře
- aplawrence.com/Unixart/sort-vs-uniq.html
Odpověď
sort | uniq
existovala před sort -u
a je kompatibilní s širší škálou systémů, ačkoli téměř všechny moderní systémy podporují -u
– je to POSIX. Je to většinou návrat do dnů, kdy sort -u
neexistovaly (a lidé nemají tendenci měnit své metody, pokud způsob, jakým vědí, nadále funguje, stačí se podívat na ifconfig
vs. ip
přijetí).
Pravděpodobně byly sloučeny, protože odstranění duplikátů v souboru vyžaduje třídění (alespoň ve standardu case) a jedná se o mimořádně běžný případ použití. Je to také interně rychlejší, protože můžete provádět obě operace současně (a vzhledem k tomu, že nevyžaduje IPC mezi uniq
a sort
). Zejména pokud je soubor velký, sort -u
pravděpodobně použije k seřazení dat méně mezilehlých souborů.
V mém systému Důsledně dostávám takové výsledky:
$ dd if=/dev/urandom of=/dev/shm/file bs=1M count=100 100+0 records in 100+0 records out 104857600 bytes (105 MB) copied, 8.95208 s, 11.7 MB/s $ time sort -u /dev/shm/file >/dev/null real 0m0.500s user 0m0.767s sys 0m0.167s $ time sort /dev/shm/file | uniq >/dev/null real 0m0.772s user 0m1.137s sys 0m0.273s
Také nezakrývá návratový kód sort
, který může být důležité (v moderních skořápkách existují způsoby, jak to získat, například pole bash
„s $PIPESTATUS
, ale toto nebylo vždy pravda).
Komentáře
- Používám
sort | uniq
, protože 9krát z 10, ‚ m ve skutečnosti používám potrubíuniq -c
. - Všimněte si, že
sort -u
byla součástí 7. vydání UNIX, kolem roku 1979. Verzesort
withou Podpora pro-u
je skutečně archaická – nebo byla napsána bez pozornosti na faktický standard před standardem POSIX ‚ s de jure. Viz také Přetečení zásobníku Řazení & uniq v linuxovém prostředí od roku 2010. - +1, protože z
ip
. To ‚ s 2016 a tento příspěvek v roce 2013, ale oip
příkazu vím jen teď. - +1 pro “ 9krát z 10 I ‚ m skutečně piping do
uniq -c
“ (a možná ještě jednou přesměrovat nasort -nr | head
). Zajímalo by mě, co je ekvivalentemsort | uniq
ve Vimu, když jsem zjistil, že Vim má:sort u
příkaz. A existuje také TILsort -u
. - Všimněte si, že při použití
sort -n | uniq
oprotisort -n -u
. Například koncové a úvodní mezery budesort -n -u
považovat za duplikáty, ale ne za první!echo -e 'test \n test' | sort -n -u
vrátítest
, aleecho -e 'test \n test' | sort -n | uniq
vrátí oba řádky.
Odpověď
Jedním rozdílem je, že uniq
má řadu užitečných dalších možností, například přeskakování polí pro srovnání a počítání počtu opakování hodnoty. Příznak sort
„s -u
implementuje pouze funkčnost nevyzdobeného uniq
příkazu.
Komentáře
- +0,49 za užitečnou odpověď, ale vyjádřil bych to jako “ Výstup
sort -u
nelze ‚ předatuniq
použít některou z těchto ‚ užitečné možnosti, jako je přeskakování polí pro srovnání a počítání počtu opakování. “ - +1 k vyrovnání naysayers protože “ neexistuje ‚ žádný způsob, jak to udělat přímo z sort “ odpovídá na otázku …
Odpověď
S POSIX sort
sa uniq
s (GNU uniq
v tomto ohledu momentálně nevyhovuje), je zde rozdíl v tom, že sort
používá porovnávací algoritmus národního prostředí k porovnání řetězců (k porovnání řetězců obvykle použije strcoll()
) zatímco uniq
kontroluje identitu bajtové hodnoty (obvykle používá strcmp()
) ¹.
To je důležité alespoň ze dvou důvodů .
-
V některých národních prostředích, zejména v systémech GNU, existují různé znaky, které se seřadí stejně. Například v národním prostředí en_US.UTF-8 v systému GNU se všechny ①②③④⑤⑥⑦⑧⑨⑩ … znaky² a mnoho dalších setřídí stejně, protože jejich pořadí řazení není definováno. Arabské číslice 0123456789 se třídí stejně jako jejich východní arabské indické protějšky (٠١٢٣٤٥٦٧٨٩).
Pro
sort -u
, ① seřadí stejně jako ② a 0123 stejně jako ٠١٢٣, takžesort -u
by si uchoval pouze jeden z nich, zatímco prouniq
(ne GNUuniq
, který používástrcoll()
(kromě-i
)), ① se liší z ② a 0123 odlišné od ٠١٢٣, takžeuniq
by všechny 4 považoval za jedinečné. -
strcoll
může porovnávat pouze řetězce platných znaků (chování je nedefinováno podle POSIXu, když má vstup sekvence bajtů, které nevytvářejí platné znaky), zatímcostrcmp()
se o to nestará o znacích, protože provádí pouze srovnání bajtů. To je další důvod, proč vámsort -u
nemusí poskytnout všechny jedinečné řádky, pokud některé z nich netvoří platný text.sort|uniq
, i když stále není specifikován pro netextový vstup, v praxi vám s větší pravděpodobností nabídne jedinečné řádky.
Kromě těchto jemností zatím nebylo zaznamenáno, že uniq
lexikálně porovnává celou řadu, zatímco sort
„s -u
porovnává na základě specifikace řazení uvedené na příkazovém řádku.
$ printf "%s\n" "a b" "a c" | sort -uk 1,1 a b $ printf "%s\n" "a b" "a c" | sort -k 1,1 | uniq a b a c $ printf "%s\n" 0 -0 +0 00 "" | sort -n | uniq 0 -0 +0 00 $ printf "%s\n" 0 -0 +0 00 "" | sort -nu 0
¹ Předchozí verze specifikace POSIX způsobovaly zmatek, ale uvedením proměnné LC_COLLATE
jako proměnné ovlivňující uniq
, která byla ve vydání z roku 2018 odstraněna a chování vyjasněné po výše zmíněné diskusi. Zobrazit odpovídající chybu skupiny Austin
² 2019 upravit . Ty byly mezitím opraveny, ale více než 95% kódových bodů Unicode má od verze 2.30 GNU libc stále nedefinované pořadí. Můžete místo toho testovat pomocí 🧙🧚🧛🧜🧝 například v novějších verzích.
Odpovědět
Dávám přednost použití sort | uniq
protože když se pokouším použít možnost -u
(eliminovat duplicity) k odstranění duplikátů zahrnujících smíšené řetězce případů, není to tak snadné pochopte výsledek.
Poznámka: Před spuštěním níže uvedených příkladů je třeba simulovat standardní porovnávací sekvenci C následujícím způsobem:
LC_ALL=C export LC_ALL
Například když chci setřídit soubor a odstranit duplikáty a současně zachovat různé případy řetězců.
$ cat short #file to sort Pear Pear apple pear Apple $ sort short #normal sort (in normal C collating sequence) Apple #the lower case words are at the end Pear Pear apple pear $ sort -f short #correctly sorts ignoring the C collating order Apple #but duplicates are still there apple Pear Pear pear $ sort -fu short #By adding the -u option to remove duplicates it is apple #difficult to ascertain the logic that sort uses to remove Pear #duplicates(i.e., why did it remove pear instead of Pear?)
Tento zmatek je vyřešen nepoužíváním možnosti -u
k odstranění duplikátů. Použití uniq
je předvídatelnější. Níže nejprve seřadí a ignoruje velká a malá písmena a poté je předá uniq
k odstranění duplikátů.
$ sort -f short | uniq Apple apple Pear pear
Komentáře
-
-u
možnostsort
vypíše první stejného běhu (viz manuálová stránka).sort -fu
tedy zachytí první výskyt každého jedinečného řádku, který nerozlišuje velká a malá písmena. Logika, kterousort
používá k odstranění duplikátů, je předvídatelná.
Odpověď
Další rozdíl, který jsem dnes zjistil, je při třídění na základě delimetru, kde sort -u
použije jedinečný příznak pouze na sloupec, se kterým seřadíte.
$ cat input.csv 3,World,1 1,Hello,1 2,Hello,1 $ cat input.csv | sort -t"," -k2 -u 1,Hello,1 3,World,1 $ cat input.csv | sort -t"," -k2 | uniq 1,Hello,1 2,Hello,1 3,World,1
Komentáře
- Toto je uvedeno v odpovědi od St é phane Chazelas, ale Líbí se mi váš příklad, takže +1
- Děkuji za poukázání na @roaima, v této odpovědi to nebylo ‚ velmi jasné