En todas partes veo a alguien que necesita obtener una lista ordenada y única, siempre se canaliza a sort | uniq
. Nunca he visto ningún ejemplo en el que alguien use sort -u
en su lugar. ¿Por qué no? ¿Cuál es la diferencia y por qué es mejor usar uniq que la marca única para ordenar?
Comentarios
- aplawrence.com/Unixart/sort-vs-uniq.html
Respuesta
sort | uniq
existía antes de sort -u
, y es compatible con una gama más amplia de sistemas, aunque casi todos los sistemas modernos admiten -u
– es POSIX. Es principalmente un retroceso a los días en que sort -u
no existía (y la gente no tiende a cambiar sus métodos si la forma que conocen continúa funcionando, solo mire ifconfig
frente a ip
adopción).
Es probable que los dos se hayan fusionado porque eliminar duplicados dentro de un archivo requiere ordenar (al menos, en el estándar case), y es un caso de uso extremadamente común de sort. También es más rápido internamente como resultado de poder realizar ambas operaciones al mismo tiempo (y debido al hecho de que no requiere IPC entre uniq
y sort
). Especialmente si el archivo es grande, sort -u
probablemente usará menos archivos intermedios para ordenar los datos.
En mi sistema Constantemente obtengo resultados como este:
$ 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
Tampoco «enmascara el código de retorno de sort
, que puede ser importante (en los shells modernos hay formas de obtener esto, por ejemplo, bash
«s $PIPESTATUS
matriz, pero esta no era siempre es cierto).
Comentarios
- Tiendo a usar
sort | uniq
porque 9 de cada 10 veces, Yo ‘ estoy realmente conectando auniq -c
. - Tenga en cuenta que
sort -u
formaba parte de la séptima edición de UNIX, alrededor de 1979. Las versiones desort
sin Los soportes para-u
son verdaderamente arcaicos, o fueron escritos sin prestar atención al estándar de facto antes del estándar de jure de POSIX ‘. Consulte también Stack Overflow Ordenar & uniq en el shell de Linux de 2010. - +1 porque de
ip
. Es ‘ s 2016 y esta publicación en 2013, pero ahora solo conozco el comandoip
. - +1 para » 9 tiempos de espera 10 I ‘ m realmente conectando a
uniq -c
» (y tal vez canalizando una vez más asort -nr | head
). Me preguntaba cuál es el equivalente asort | uniq
en Vim cuando descubrí que Vim tiene el comando:sort u
. Y TILsort -u
también existe. - Tenga en cuenta que hay una diferencia entre
sort -n | uniq
ysort -n -u
. Por ejemplo,sort -n -u
verá los espacios en blanco al principio y al final como duplicados, ¡pero no el primero!echo -e 'test \n test' | sort -n -u
devuelvetest
, peroecho -e 'test \n test' | sort -n | uniq
devuelve ambas líneas.
Respuesta
Una diferencia es que uniq
tiene varias opciones adicionales útiles, como omitir campos para comparar y contar el número de repeticiones de un valor. sort
«s -u
solo implementa la funcionalidad del comando sin adornos uniq
.
Comentarios
- +0.49 para una respuesta útil, pero lo expresaría algo como » El resultado de
sort -u
¿se puede ‘ t pasarse auniq
para usar algunos de los últimos ‘ s opciones útiles, como omitir campos para comparar y contar el número de repeticiones. » - +1 para compensar el detractores porque » hay ‘ no hay forma de hacer esto directamente desde sort » ¿ responde la pregunta …
Responder
Con sort
sy uniq
s (GNU uniq
no cumple actualmente en ese sentido), hay una diferencia en el sentido de que sort
usa el algoritmo de clasificación de la configuración regional para comparar cadenas (normalmente se usará strcoll()
para comparar cadenas) mientras que uniq
comprueba la identidad del valor de byte (normalmente utilizará strcmp()
) ¹.
Eso es importante por al menos dos razones .
-
En algunas configuraciones regionales, especialmente en sistemas GNU, hay diferentes caracteres que ordenan lo mismo. Por ejemplo, en el entorno local en_US.UTF-8 de un sistema GNU, todos los ①②③④⑤⑥⑦⑧⑨⑩ … caracteres² y muchos otros se ordenan de la misma manera porque su orden de clasificación no está definido. Los dígitos árabes 0123456789 se ordenan de la misma manera que sus contrapartes árabe oriental índico (٠١٢٣٤٥٦٧٨٩).
Para
sort -u
, ① ordena lo mismo que ② y 0123 lo mismo que ٠١٢٣, por lo quesort -u
retendría solo uno de cada, mientras que parauniq
(no GNUuniq
que usastrcoll()
(excepto con-i
)), ① es diferente de ② y 0123 diferente de ٠١٢٣, por lo queuniq
consideraría los 4 únicos. -
strcoll
solo puede comparar cadenas de caracteres válidos (el comportamiento no está definido según POSIX cuando la entrada tiene secuencias de bytes que no forman caracteres válidos) mientras que astrcmp()
no le importa sobre los caracteres, ya que solo hace una comparación byte a byte. Así que esa es otra razón por la quesort -u
puede no darle todas las líneas únicas si algunas de ellas no forman un texto válido.sort|uniq
, aunque todavía no se especifica en la entrada que no es de texto, en la práctica es más probable que le proporcione líneas únicas por ese motivo.
Además de esas sutilezas, una cosa que no se ha notado hasta ahora es que uniq
compara léxicamente la línea completa, mientras que sort
«s -u
compara según la especificación de clasificación proporcionada en la línea de comando.
$ 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
¹ Sin embargo, las versiones anteriores de la especificación POSIX estaban causando confusión al enumerar la variable LC_COLLATE
como una que afectaba a uniq
, que se eliminó en la edición de 2018 y el comportamiento se aclaró siguiendo esa discusión mencionada anteriormente. Consulte el error de grupo de Austin correspondiente
² 2019 editar . Desde entonces se han solucionado, pero más del 95% de los puntos de código Unicode todavía tienen un orden indefinido a partir de la versión 2.30 de la libc de GNU . Puede probar con 🧙🧚🧛🧜🧝 en su lugar, por ejemplo, en versiones más recientes
Respuesta
Prefiero usar sort | uniq
porque cuando intento usar la opción -u
(eliminar duplicados) para eliminar duplicados que involucran cadenas de mayúsculas y minúsculas mixtas, no es tan fácil comprender el resultado.
Nota: antes de que pueda ejecutar los ejemplos a continuación, debe simular la secuencia de clasificación estándar de C haciendo lo siguiente:
LC_ALL=C export LC_ALL
Por ejemplo, si quiero ordenar un archivo y eliminar duplicados, mientras que al mismo tiempo, mantengo distintos casos de cadenas.
$ 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?)
Esta confusión se resuelve al no usar la opción -u
para eliminar duplicados. Usar uniq
es más predecible. Lo siguiente primero ordena e ignora el caso y luego lo pasa a uniq
para eliminar los duplicados.
$ sort -f short | uniq Apple apple Pear pear
Comentarios
-
-u
opción desort
genera la primera de una ejecución igual (ver página de manual). Por lo tanto,sort -fu
detecta la primera aparición de cada línea única que no distingue entre mayúsculas y minúsculas. La lógica quesort
usa para eliminar duplicados es predecible.
Respuesta
Otra diferencia que descubrí hoy es cuando se ordena según un delimitador donde sort -u
aplica la marca única solo en la columna con la que se ordena.
$ 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
Comentarios
- Esto se menciona en una respuesta de St é phane Chazelas pero Me gusta tu ejemplo, así que +1
- Gracias por señalar a @roaima, no fue ‘ t muy claro en esa respuesta