
Estoy intentando ordenar algunos datos usando sort
. Noté que ordenaba por dígitos en lugar de números, así que agregué la -n
bandera. Sin embargo, aparentemente solo ordena numéricamente en el primer campo. Desglosarlo por campo es un problema ya que las líneas tienen distintos números de campos (y, francamente, no puedo entender su comportamiento). Aquí hay algunos datos de muestra bastante cercanos con los que estaba jugando:
echo -e "b b 1\n23 44\nb 3\na 7\nb b 2\na 1\nb a 10\nb b 10\nb 1\nb a 1\n18 2\nb 10\n18 15\nb a 2\n23 9\nb 2" | sort -n
Input Want Expect? sort -n -n -k1,1 -k2,2 -k3,3 -k4,4…
b b 1 8 2 a 1 23 44 a 1 b a 1
23 44 8 15 a 7 23 9 a 7 b a 10
b 3 23 9 b a 1 8 15 b 1 b a 2
a 7 23 44 b a 2 8 2 b 10 b b 1
b b 2 a 1 b a 10 a 1 b 2 b b 10
a 1 a 7 b b 1 a 7 b 3 b b 2
b a 10 b 1 b b 2 b 1 b a 1 a 1
b b 10 b 2 b b 10 b 10 b a 10 b 1
b 1 b 3 b 1 b 2 b a 2 b 2
b a 1 b 10 b 2 b 3 b b 1 b 3
8 2 b a 1 b 3 b a 1 b b 10 a 7
b 10 b a 2 b 10 b a 10 b b 2 b 10
8 15 b a 10 8 2 b a 2 8 15 8 2
b a 2 b b 1 8 15 b b 1 8 2 8 15
23 9 b b 2 23 9 b b 10 23 44 23 9
b 2 b b 10 23 44 b b 2 23 9 23 44
Idealmente, me gustaría que funcione en esa misma máquina, que tiene GNU coreutils tipo 5.93. Me gustaría manejarlo con herramientas simples de Unix; No quiero simplemente pasarle el problema a Perl, etc. Espero un equivalente del [imaginario]sort --numeric-sort --all-fields --actually-work
Respuesta1
Creo que tu problema es que no entiendes lo sort
que estás haciendo. La clasificación básica se basa en valores de caracteres ASCII, donde los números están antes de mayúsculas y éstas antes de minúsculas: '1' == 49, 'A' == 65, 'a' = 97. Eso explica la sort
columna, donde números como '23 ' está ordenado antes de '8 ', que está antes de 'b b': el valor ASCII para '2' es 50, el valor ASCII para '8' es 56 y para 'b' es 98.
Al ordenar numéricamente ( sort -n
), las entradas no numéricas se ordenan mediante el método normal, pero se interpretan como cero en comparación con números, como 23 u 8; pero como el valor se trata como un número, no como un valor de carácter, '8' está antes de '23'. Entonces las entradas alfabéticas se ordenarán antes que las entradas numéricas.
Lo mejor que puede hacer es normalizar los datos para que cada columna tenga el mismo tipo de valor: ya sea todos números o todos alfanuméricos, y ordenarlos adecuadamente.
En la última columna (ordenar por campo), ordenará primero las entradas con más campos, ya que está especificando explícitamente 4 (o más) campos. Entonces (1,2,3) estaría antes de (1,2). Sin la -k
opción, ordenar tiene en cuenta la línea en su conjunto.
Puedes leer más información en elinformación coreutils ordenarpágina.
Respuesta2
echo -e "b b 1\n23 44\nb 3\na 7\nb b 2\na 1\nb a 10\nb b 10\nb 1\nb a 1\n18 2\nb 10\n18 15\nb a 2\n23 9\nb 2" \
| sed -r 's/[a-z]/9999&/g' | sort -n -k1 -k2 -k3 | sed 's/9999//g'
18 2
18 15
23 9
23 44
a 1
b 1
b 2
b 3
a 7
b 10
b a 1
b b 1
b a 2
b b 2
b a 10
b b 10
¿Es esto lo que quieres? ¿Ordenar numéricamente, si es numérico, y números antes que otros caracteres?
Le prefijo a cada cadena un número alto, para poner las cadenas al final al ordenarlas y elimino los números altos (9999) al final.
Respuesta3
Con el beneficio de algunos años de desarrollo, sort -V
produce sort 8.26
solo el resultado deseado:
$ echo -e "b b 1\n23 44\nb 3\na 7\nb b 2\na 1\nb a 10\nb b 10\nb 1\nb a 1\n8 2\nb 10\n8 15\nb a 2\n23 9\nb 2" \
| sort -V
8 2
8 15
23 9
23 44
a 1
a 7
b 1
b 2
b 3
b 10
b a 1
b a 2
b a 10
b b 1
b b 2
b b 10