Jaký je rozdíl mezi “ sort -u ” a “ sort | uniq ”?

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

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. Verze sort 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 o ip 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 na sort -nr | head). Zajímalo by mě, co je ekvivalentem sort | uniq ve Vimu, když jsem zjistil, že Vim má :sort u příkaz. A existuje také TIL sort -u.
  • Všimněte si, že při použití sort -n | uniq oproti sort -n -u. Například koncové a úvodní mezery bude sort -n -u považovat za duplikáty, ale ne za první! echo -e 'test \n test' | sort -n -u vrátí test, ale echo -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ředat uniq 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že sort -u by si uchoval pouze jeden z nich, zatímco pro uniq (ne GNU uniq, který používá strcoll() (kromě -i)), ① se liší z ② a 0123 odlišné od ٠١٢٣, takže uniq 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ímco strcmp() se o to nestará o znacích, protože provádí pouze srovnání bajtů. To je další důvod, proč vám sort -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žnost sort 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, kterou sort 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é

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *