¿Cuál es la diferencia entre “ sort -u ” y “ sort | uniq ”?

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

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 a uniq -c.
  • Tenga en cuenta que sort -u formaba parte de la séptima edición de UNIX, alrededor de 1979. Las versiones de sort 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 comando ip.
  • +1 para » 9 tiempos de espera 10 I ‘ m realmente conectando a uniq -c » (y tal vez canalizando una vez más a sort -nr | head). Me preguntaba cuál es el equivalente a sort | uniq en Vim cuando descubrí que Vim tiene el comando :sort u. Y TIL sort -u también existe.
  • Tenga en cuenta que hay una diferencia entre sort -n | uniq y sort -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 devuelve test, pero echo -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 a uniq 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 que sort -u retendría solo uno de cada, mientras que para uniq (no GNU uniq que usa strcoll() (excepto con -i)), ① es diferente de ② y 0123 diferente de ٠١٢٣, por lo que uniq 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 a strcmp() 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 que sort -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 de sort 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 que sort 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

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *