¿Cuál es la diferencia entre las opciones --general-numeric-sort y --numeric-sort en gnu sort

113

sortproporciona dos tipos de ordenación numérica. Esto es de la página del manual:

   -g, --general-numeric-sort
          compare according to general numerical value

   -n, --numeric-sort
          compare according to string numerical value

¿Cual es la diferencia?

Trenton
fuente
17
Tenga en cuenta que la documentación completa sortno es la manpágina sino la infopágina ( info sort).
a3nm

Respuestas:

85

La ordenación numérica general compara los números como flotantes, esto permite la notación científica, por ejemplo, 1.234E10 pero es más lento y está sujeto a errores de redondeo (1.2345678 podría venir después de 1.2345679), la ordenación numérica es solo una ordenación alfabética regular que sabe que 10 viene después de 9.

Ver http://www.gnu.org/software/coreutils/manual/html_node/sort-invocation.html

'-g' '--general-numeric-sort' '--sort = general-numeric' Ordena numéricamente, usando la función C estándar strtod para convertir un prefijo de cada línea en un número de punto flotante de doble precisión. Esto permite especificar números de coma flotante en notación científica, como 1.0e-34 y 10e100. La configuración regional LC_NUMERIC determina el carácter del punto decimal. No informe errores de desbordamiento, subdesbordamiento o conversión. Utilice la siguiente secuencia de clasificación: Líneas que no comienzan con números (se consideran todas iguales). NaN (valores “No es un número”, en aritmética de coma flotante IEEE) en un orden consistente pero dependiente de la máquina. Menos infinito. Números finitos en orden numérico ascendente (con -0 y +0 iguales). Más infinito.

Utilice esta opción solo si no hay otra alternativa; es mucho más lento que --numeric-sort (-n) y puede perder información al convertir a punto flotante.

'-n' '--numeric-sort' '--sort = numeric' Ordenar numéricamente. El número comienza cada línea y consta de espacios en blanco opcionales, un signo '-' opcional y cero o más dígitos posiblemente separados por separadores de miles, seguidos opcionalmente por un carácter de punto decimal y cero o más dígitos. Un número vacío se trata como '0'. El entorno local LC_NUMERIC especifica el carácter de punto decimal y el separador de miles. De forma predeterminada, un espacio en blanco es un espacio o una pestaña, pero la configuración regional LC_CTYPE puede cambiar esto.

La comparación es exacta; no hay error de redondeo.

No se reconoce ni un '+' inicial ni una notación exponencial. Para comparar dichas cadenas numéricamente, use la opción --general-numeric-sort (-g).

Martin Beckett
fuente
2
Gracias. Es extraño que las páginas de información y el hombre no tengan esto. Tampoco sabía sobre gnu.org/software/coreutils/manual/html_node/index.html .
Trenton
6
Estas cosas no me funcionan. Estoy ordenando un archivo con una tercera columna con contenidos como R1 R2 R10 R15. Usando -k3.2no -k3.2g, está ordenando R10antes R2. El tipo es lexicográfico, no numérico. Espero que trate el campo desde el segundo carácter en adelante como un número.
Kaz
6
@Kaz: sortespecificaciones clave. son verdaderamente bizantinos - el corto es: el espacios en blanco que preceden al campo se consideran parte del campo , por lo que char. El índice 1 apunta al (primer) espacio en blanco que precede al campo, no al primer carácter real del campo. Sufijo el char. index with bpara solucionar este problema, es decir: -k 3.2bn,3(tenga en cuenta que la opción global no funciona en este caso). También tenga en cuenta lo agregado , que garantiza que solo se use el tercer campo; sin ese segundo índice de campo, se usa el resto de la línea completa . -b,3
mklement0
11

Debe tener cuidado con su localidad. Por ejemplo, podría intentar ordenar un número flotante (como 2.2) mientras que su configuración regional podría esperar el uso de una coma (como 2,2).

Como se informó en este foro , es posible que obtenga resultados incorrectos al utilizar los indicadores -no -g.

En mi caso uso:

LC_ALL=C sort -k 6,6n file

para ordenar la sexta columna que contiene:

2.5
3.7
1.4

para obtener

1.4
2.5
3.7
JFL
fuente
2
Incluso con LANG = C, no puedo -nreconocer la coma como un separador de miles: "1,000" se trata de la misma manera que "1".
Scott
1
Eso debería ser LC_ALL = C.
Stuart P. Bentley
@Scott: De hecho, los separadores de miles NO se reconocen: sortusa la lógica del prefijo más largo : se usa la parte más larga de la línea / tecla que reconoce como un número; en una configuración regional que utiliza .como carácter de base, dejará de leer en ,.
mklement0
@ StuartP.Bentley: de LC_ALL=Checho, es la opción más sólida ; sin embargo, si LC_ALLno se establece la apuesta, LANG=Ctambién funcionará.
mklement0
1
Buen punto, pero LANG=C sort -k 6,6n filees más simple y también localiza el efecto de establecer la variable de entorno LANGen el comando específico.
mklement0
0

Además de la respuesta aceptada que menciona -gpermitir la notación científica , quiero mostrar la parte que más probablemente causa un comportamiento indeseable.

Con -g:

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=en_US.UTF-8 sort -g myfile
baa
--inf
--inf  
--inf- 
--inf--
--inf-a
--nnf
nnf--
   nnn  
tnan
zoo
   naN
Nana
nani lol
-inf
-inf--
-11
-2
-1
1
+1
2
+2
0xa
11
+11
inf

Mire las zootres cosas importantes aquí:

  • La línea comienza con NAN(por ejemplo, Nanay nani lol) o -INF(un guión, no --INF) se mueve al final pero antes de los dígitos. Mientras se INFmueve al último dígito posterior porque significa infinito .

  • Los NAN, INFy no -INFdistinguen entre mayúsculas y minúsculas .

  • Las líneas siempre se ignoran los espacios en blanco a cada lado de NAN, INF, -INF (sin tener en cuenta LC_CTYPE). Otros alfabéticos pueden ignorar los espacios en blanco de cualquier lado dependiendo de la configuración regional LC_COLLATE(por ejemplo, LC_COLLATE=fr_FR.UTF-8ignorar pero LC_COLLATE=us_EN.UTF-8no ignorar).

Entonces, si está ordenando alfanuméricos arbitrarios , probablemente no lo desee -g. Si realmente necesita una comparación de notación científica -g, probablemente desee extraer datos alfabéticos y numéricos y hacer la comparación por separado .

Si solo necesita una 1, -1clasificación de números ordinarios (por ejemplo ), y cree que 0x/E/+ sortingno es importante, use lo -nsuficiente:

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=en_US.UTF-8 sort -n myfile
-1000
-22
-13
-11
-010
-10
-5
-2
-1
-0.2
-0.12
-0.11
-0.1
0x1
0x11
0xb
+1
+11
+2
-a
-aa
--aa
-aaa
-b
baa
BAA
bbb
+ignore
inf
-inf
--inf
--inf  
--inf- 
--inf--
-inf--
--inf-a
   naN
Nana
nani lol
--nnf
nnf--
   nnn  
None         
uum
Zero cool
-zzz
1
1.1
1.234E10
5
11

O -gbien -n, tenga en cuenta el efecto local . Es posible que desee especificar LC_NUMERICcomo us_EN.UTF-8 para evitar la clasificación de fr_FR.UTF-8 -con un número flotante fallido :

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=fr_FR.UTF-8 sort -n myfile
-10
-5
-2
-1
-1.1
-1.2
-0.1
-0.11
-0.12
-0.2
-a
+b
middle
-wwe
+zoo
1
1.1

Con LC_NUMERIC=en_US.UTF-8:

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=en_US.UTF-8 sort -n myfile
-10
-5
-2
-1.2
-1.1
-1
-0.2
-0.12
-0.11
-0.1
-a
+b
middle
-wwe
+zoo
1
1.1

O LC_NUMERIC=us_EN.UTF-8para agrupar +|-|spacecon alpha:

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=us_EN.UTF-8 sort -n myfile
-0.1
    a
    b
 a
 b
+b
+zoo
-a
-wwe
middle
1

Probablemente desee especificar localeal usar sortsi desea escribir un script portátil.

Fruta
fuente