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 -ubyla součástí 7. vydání UNIX, kolem roku 1979. Verzesortwithou Podpora pro-uje 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 oippří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 | uniqve Vimu, když jsem zjistil, že Vim má:sort upříkaz. A existuje také TILsort -u. - Všimněte si, že při použití
sort -n | uniqoprotisort -n -u. Například koncové a úvodní mezery budesort -n -upovažovat za duplikáty, ale ne za první!echo -e 'test \n test' | sort -n -uvrátítest, aleecho -e 'test \n test' | sort -n | uniqvrá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 -unelze ‚ předatuniqpouží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 -uby 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žeuniqby všechny 4 považoval za jedinečné. -
strcollmůž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 -unemusí 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
-
-umožnostsortvypíše první stejného běhu (viz manuálová stránka).sort -futedy zachytí první výskyt každého jedinečného řádku, který nerozlišuje velká a malá písmena. Logika, kterousortpouží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é