Especifique el orden de clasificación con LC_COLLATE para que las minúsculas estén antes que las mayúsculas

16

Dado el archivo:

$ cat file
1
a
C
B
2
c
3
A
b

Por defecto sort:

$ sort file
1
2
3
a
A
b
B
c
C

Con LC_COLLATE=Cso se ordenará en mayúscula antes de minúscula:

$ LC_COLLATE=C sort file
1
2
3
A
B
C
a
b
c

¿Es posible obtener una clasificación para revertir el orden de las mayúsculas y minúsculas, es decir dígitos, minúsculas y mayúsculas?

iiSeymour
fuente

Respuestas:

8

No conozco ninguna configuración regional que, por defecto, se ordene en ese orden. La solución es crear una configuración regional personalizada con un orden de clasificación personalizado. Si alguien, cuatro años después, quiere ordenar de manera personalizada, este es el truco.

La gran mayoría de las configuraciones regionales no especifican su propio orden de clasificación, sino que copian el orden de clasificación definido de /usr/share/i18n/locales/iso14651_t1_commonmodo que eso es lo que querrá editar. En lugar de cambiar el orden de clasificación para casi todas las configuraciones regionales modificando el original iso14651_t1_common, le sugiero que haga una copia. Los detalles sobre cómo funciona el orden de clasificación y cómo crear una configuración regional personalizada en su $HOMEdirectorio sin acceso a la raíz se encuentran en esta respuesta a una pregunta similar .

Eche un vistazo a cómo ay Ase ordenan en función de sus entradas en iso14651_t1_common:

<U0061> <a>;<BAS>;<MIN>;IGNORE # 198 a
<U0041> <a>;<BAS>;<CAP>;IGNORE # 517 A

by Bson similares:

<U0062> <b>;<BAS>;<MIN>;IGNORE # 233 b
<U0042> <b>;<BAS>;<CAP>;IGNORE # 550 B

Vemos que en la primera pasada, tanto ay Atener el símbolo de cotejo <a>, mientras tanto by Btienen el símbolo cotejo <b>. Ya <a>aparece antes <b>en iso14651_t1_common, ay Aestán atados antes by B. La segunda pasada no rompe los lazos porque los cuatro caracteres tienen el símbolo de clasificación <BAS>, pero durante la tercera pasada los lazos se resuelven porque el símbolo de clasificación para letras minúsculas <MIN>aparece en la línea 3467, antes del símbolo de clasificación para letras mayúsculas <CAP>(línea 3488) . Por lo que el orden de clasificación termina como a, A, b, B.

Intercambiar el primer y el tercer símbolo de clasificación ordenaría las letras primero por mayúsculas y minúsculas, luego por acento ( <BAS>significa no acentuado), luego por orden alfabético. Sin embargo , tanto <MIN>y <CAP>venir antes de los dígitos numéricos, así que esto tendría el efecto no deseado de poner dígitos después de las letras.

La forma más fácil de mantener los dígitos primero mientras se hacen que todas las letras minúsculas aparezcan antes de todas las letras mayúsculas es forzar que todas las letras se unan durante la primera comparación estableciéndolas todas iguales <a>. Para asegurarse de que se ordenan alfabéticamente dentro de mayúsculas y minúsculas, cambie el último símbolo de clasificación IGNOREal primer símbolo de clasificación actual. Siguiendo este patrón, ase convertiría en:

<U0061> <a>;<BAS>;<MIN>;<a> # 198 a

A se convertiría:

<U0041> <a>;<BAS>;<CAP>;<a> # 517 A

b se convertiría:

<U0062> <a>;<BAS>;<MIN>;<b> # 233 b

B se convertiría:

<U0042> <a>;<BAS>;<CAP>;<b> # 550 B

y así sucesivamente para el resto de las letras.

Una vez que haya creado una versión personalizada de iso14651_t1_common, siga las instrucciones en la respuesta vinculada anteriormente para compilar su configuración regional personalizada.

beandip
fuente
6

La configuración LC_COLLATE=Cno siempre es suficiente para ordenar mayúsculas antes que minúsculas. Es posible que necesite configurar LC_ALL=C.

Eso también tendrá en cuenta los caracteres no alfanuméricos e incluso no imprimibles, pero si no desea que haya opciones -dy -i(como se describe en man sort), lo desactivará.

Sin embargo, probablemente fallará gravemente con la entrada multibyte, como UTF-8 con caracteres no ASCII.

Para obtener minúsculas (en orden) antes de mayúsculas (en orden), la mejor manera en que puedo pensar que no implica romper un lenguaje de programación completo es invertir el caso de todas las letras antes de la ordenación e invertirlas nuevamente después.

tr 'a-zA-Z' 'A-Za-z' < file | LC_ALL=C sort | tr 'a-zA-Z' 'A-Za-z'
Ley29
fuente
2

No soy un experto, pero nunca he visto una configuración regional que defina la clasificación de esta manera. AFAIK esta colación es solo en C donde se basa en valores ASCII . (Normalmente, solo resolvería esto con un script).

Sin embargo, nunca he hecho esto, pero es posible que desee consultar las páginas de manual localedef (1) y locale (5) para comprender cómo se definen las configuraciones regionales y, finalmente, definir la suya propia.

Además, no olvide que si hay signos diacríticos o caracteres especiales, la configuración regional de C no los tratará como desee. Por ejemplo, no se colocará ácerca ao Łcerca L. En tales casos, la localización nativa del idioma sería probablemente un mejor punto de partida.

Alois Mahdal
fuente
0

Creo que la respuesta es sin necesidad de LC_COLLATE cambiado (lo que significa dejar la función como comportamiento predeterminado):

ordenar archivo -f

Esto funciona en Linux; consulte su sección de ayuda para el comando en caso de que esté en Unix y ejecute una versión diferente. -f se define como ignorar mayúsculas y minúsculas.

Gracias por la corrección y edición rápida (y extrañamente) de la gramática equivocada, Stephen Rauch.

1m.0g
fuente
-1
LC_COLLATE="en_US.UTF-8" sort file
unxnut
fuente
¿Esto no ordena minúsculas antes mayúsculas? ideone.com/Gtyg4Z
iiSeymour
Hmm, en mi caso, lo hizo usando tu ejemplo.
unxnut
44
@unxnut Esto es incorrecto. Sin el punto y coma, el comando establecería el entorno para sort, pero con el punto y coma, la variable es local para el shell y no afecta el comportamiento de sort. El punto y coma podría mantenerse como está si la variable también se exporta, pero eso afectaría también a otros comandos.
Anders Sjöqvist