Quelle est la différence entre “ sort -u ” et “ sort | uniq ”?

Partout où je vois quelquun qui a besoin dobtenir une liste triée et unique, il dirige toujours vers sort | uniq. Je nai jamais vu dexemples où quelquun utilise à la place sort -u. Pourquoi pas? Quelle est la différence, et pourquoi vaut-il mieux utiliser uniq que lindicateur unique pour trier?

Commentaires

Réponse

sort | uniq existait avant sort -u, et est compatible avec une plus large gamme de systèmes, bien que presque tous les systèmes modernes prennent en charge -u – cest POSIX. Cest surtout un retour en arrière à lépoque où sort -u nexistait pas (et les gens nont pas tendance à changer de méthode si la façon dont ils savent continue de fonctionner, il suffit de regarder ifconfig vs ip adoption).

Les deux ont probablement été fusionnés car la suppression des doublons dans un fichier nécessite un tri (au moins, dans la norme case) et est un cas dutilisation extrêmement courant de sort. Il est également plus rapide en interne car il peut effectuer les deux opérations en même temps (et du fait quil ne nécessite pas dIPC entre uniq et sort). Surtout si le fichier est volumineux, sort -u utilisera probablement moins de fichiers intermédiaires pour trier les données.

Sur mon système Jobtiens systématiquement des résultats comme celui-ci:

$ 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 

Il ne masque pas non plus le code de retour de sort, qui peut être important (dans les shells modernes, il existe des moyens dobtenir ceci, par exemple, bash « s $PIPESTATUS tableau, mais ce nétait pas » t toujours vrai).

Commentaires

  • Jai tendance à utiliser sort | uniq car 9 fois sur 10, Je ‘ m en fait la tuyauterie vers uniq -c.
  • Notez que sort -u faisait partie de la 7e édition UNIX, vers 1979. Versions de sort sans Les supports de -u sont vraiment archaïques – ou ont été écrits sans attention au standard de facto avant le standard de jure POSIX ‘. Voir aussi Stack Overflow Trier & uniq dans le shell Linux à partir de 2010.
  • +1 car sur ip. Il ‘ s 2016 et ce post en 2013, mais je ne connais que la commande ip maintenant.
  • +1 pour  » 9 fois 10 Je ‘ m en train de rediriger vers uniq -c  » (et peut-être encore une fois le redirection vers sort -nr | head). Je me demandais quel était léquivalent de sort | uniq dans Vim quand jai découvert que Vim avait la commande :sort u. Et TIL sort -u existe également.
  • Notez quil existe une différence entre lutilisation de sort -n | uniq et de sort -n -u. Par exemple, les espaces de fin et de début seront considérés comme des doublons par sort -n -u mais pas par le premier! echo -e 'test \n test' | sort -n -u renvoie test, mais echo -e 'test \n test' | sort -n | uniq renvoie les deux lignes.

Réponse

Une différence est que uniq a un certain nombre doptions supplémentaires utiles, telles que sauter des champs pour la comparaison et compter le nombre de répétitions dune valeur. Lindicateur sort « s -u implémente uniquement la fonctionnalité de la commande sans ornements uniq.

Commentaires

  • +0.49 pour une réponse utile, mais je la formulerais quelque chose comme  » La sortie de sort -u peut ‘ être transmis à uniq pour utiliser certains de ces derniers ‘ les options utiles, telles que lignorance des champs de comparaison et le comptage du nombre de répétitions.  »
  • +1 pour compenser le Naysayers car  » il ny a ‘ aucun moyen de le faire directement à partir du tri  » répond à la question …

Réponse

Avec les sort et uniq s (GNU uniq nest actuellement pas conforme à cet égard), il « sa différence en ce que sort utilise lalgorithme de classement des paramètres régionaux pour comparer les chaînes (utilisera généralement strcoll() pour comparer les chaînes) tandis que uniq vérifie lidentité de la valeur doctet (utilise généralement strcmp()) ¹.

Cela compte pour au moins deux raisons .

  • Dans certains paramètres régionaux, en particulier sur les systèmes GNU, il existe différents caractères qui trient de la même manière. Par exemple, dans la locale en_US.UTF-8 sur un système GNU, tous les caractères ①②③④⑤⑥⑦⑧⑨⑩ …² et bien dautres sont triés de la même manière car leur ordre de tri nest pas défini. Les chiffres arabes 0123456789 sont triés de la même manière que leurs équivalents Indiens de larabe oriental (٠١٢٣٤٥٦٧٨٩).

    Pour sort -u, ① trie de la même manière que ② et 0123 de la même manière que ٠١٢٣ afin que sort -u nen conserve quun de chaque, tandis que pour uniq (pas GNU uniq qui utilise strcoll() (sauf avec -i)), ① est différent de ② et 0123 différent de ٠١٢٣, donc uniq considérerait les 4 comme uniques.

  • strcoll ne peut comparer que des chaînes de caractères valides (le comportement nest pas défini selon POSIX lorsque lentrée contient des séquences doctets qui ne forment pas de caractères valides) tandis que strcmp() ne se soucie pas à propos des caractères car il ne fait que la comparaison octet à octet. Cest donc une autre raison pour laquelle sort -u peut ne pas vous donner toutes les lignes uniques si certaines dentre elles ne forment pas de texte valide. sort|uniq, bien que toujours non spécifié sur la saisie non textuelle, en pratique, il est plus susceptible de vous donner des lignes uniques pour cette raison.

A côté de ces subtilités, une chose qui na pas été notée jusquà présent est que uniq compare la ligne entière lexicalement, tandis que sort « s -u compare en fonction de la spécification de tri donnée sur la ligne de commande.

$ 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 

¹ Cependant, les versions précédentes de la spécification POSIX semaient la confusion en listant la variable LC_COLLATE comme une variable affectant uniq, qui a été supprimée dans lédition 2018 et le comportement a été clarifié suite à la discussion mentionnée ci-dessus. Voir le bogue du groupe Austin correspondant

² 2019 modifier . Ceux-ci ont été corrigés depuis, mais plus de 95% des points de code Unicode ont toujours un ordre non défini à partir de la version 2.30 de la libc GNU . Vous pouvez tester avec 🧙🧚🧛🧜🧝 à la place par exemple dans les versions plus récentes

Answer

Je préfère utiliser sort | uniq car lorsque jessaie dutiliser loption -u (éliminer les doublons) pour supprimer les doublons impliquant des chaînes de casse mixtes, il nest pas si facile de comprendre le résultat.

Remarque: avant de pouvoir exécuter les exemples ci-dessous, vous devez simuler la séquence de classement C standard en procédant comme suit:

LC_ALL=C export LC_ALL 

Par exemple, si je veux trier un fichier et supprimer les doublons, tout en gardant en même temps les différents cas de chaînes distincts.

$ 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?) 

Cette confusion est résolue en nutilisant pas loption -u pour supprimer les doublons. Lutilisation de uniq est plus prévisible. Ce qui suit trie et ignore dabord le cas, puis le transmet à uniq pour supprimer les doublons.

$ sort -f short | uniq Apple apple Pear pear 

Commentaires

  • -u option de sort renvoie le premier dune exécution égale (voir page de manuel). Ainsi, sort -fu prend la première occurrence de chaque ligne unique insensible à la casse. La logique utilisée par sort pour supprimer les doublons est prévisible.

Réponse

Une autre différence que jai découverte aujourdhui est le tri basé sur un délimiteur où sort -u applique lindicateur unique uniquement sur la colonne avec laquelle vous effectuez le tri.

$ 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 

Commentaires

  • Ceci est mentionné dans une réponse de St é phane Chazelas mais Jaime votre exemple, alors +1
  • Merci davoir signalé @roaima, ce nétait ‘ pas très clair dans cette réponse

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *