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
- aplawrence.com/Unixart/sort-vs-uniq.html
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 versuniq -c
. - Notez que
sort -u
faisait partie de la 7e édition UNIX, vers 1979. Versions desort
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 commandeip
maintenant. - +1 pour » 9 fois 10 Je ‘ m en train de rediriger vers
uniq -c
» (et peut-être encore une fois le redirection verssort -nr | head
). Je me demandais quel était léquivalent desort | uniq
dans Vim quand jai découvert que Vim avait la commande:sort u
. Et TILsort -u
existe également. - Notez quil existe une différence entre lutilisation de
sort -n | uniq
et desort -n -u
. Par exemple, les espaces de fin et de début seront considérés comme des doublons parsort -n -u
mais pas par le premier!echo -e 'test \n test' | sort -n -u
renvoietest
, maisecho -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 quesort -u
nen conserve quun de chaque, tandis que pouruniq
(pas GNUuniq
qui utilisestrcoll()
(sauf avec-i
)), ① est différent de ② et 0123 différent de ٠١٢٣, doncuniq
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 questrcmp()
ne se soucie pas à propos des caractères car il ne fait que la comparaison octet à octet. Cest donc une autre raison pour laquellesort -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 desort
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 parsort
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