Specificare l'ordinamento con LC_COLLATE in modo che le lettere minuscole siano prima delle maiuscole


16

Dato il file:

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

Per impostazione predefinita sort:

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

Con LC_COLLATE=Ccosì ordinerà in lettere maiuscole prima di lettere minuscole:

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

È possibile ottenere l'ordinamento per invertire l'ordinamento del caso, ovvero cifre, minuscole e maiuscole?

Risposte:


8

Non conosco alcun locale che, per impostazione predefinita, ordina in questo ordine. La soluzione è creare un'impostazione internazionale personalizzata con un ordinamento personalizzato. Se qualcuno, quattro anni dopo, vuole ordinare in modo personalizzato, ecco il trucco.

La stragrande maggioranza delle versioni locali non specifica il proprio ordinamento, ma piuttosto copia l'ordinamento definito in /usr/share/i18n/locales/iso14651_t1_commonmodo che sia ciò che si desidera modificare. Invece di cambiare l'ordinamento per quasi tutte le impostazioni locali modificando l'originale iso14651_t1_common, ti suggerisco di fare una copia. I dettagli su come funziona l'ordinamento e su come creare un'impostazione internazionale personalizzata nella $HOMEdirectory senza accesso root si trovano in questa risposta a una domanda simile .

Dai un'occhiata a come ae Asono ordinati in base alle loro voci in iso14651_t1_common:

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

be Bsono simili:

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

Lo vediamo al primo passaggio, entrambi ae Ahanno il simbolo di fascicolazione <a>, mentre entrambi be Bhanno il simbolo di fascicolazione <b>. Poiché <a>appare prima <b>in iso14651_t1_common, ae Asono legati prima be B. Il secondo passaggio non rompe i legami perché tutti e quattro i caratteri hanno il simbolo di fascicolazione <BAS>, ma durante il terzo passaggio i legami vengono risolti perché il simbolo di fascicolazione per le lettere minuscole <MIN>appare sulla riga 3467, prima del simbolo di fascicolazione per le lettere maiuscole <CAP>(linea 3488) . Così l'ordinamento finisce come a, A, b, B.

Scambiando il primo e il terzo simbolo di fascicolazione <BAS>, le lettere vengono ordinate prima per caso (in basso, poi in alto), quindi per accento ( significa non accentate), quindi per ordine alfabetico. Tuttavia , entrambi <MIN>e <CAP>vengono prima delle cifre numeriche, quindi ciò avrebbe l'effetto indesiderato di inserire le cifre dopo le lettere.

Il modo più semplice per mantenere prima le cifre mentre tutte le lettere minuscole vengono prima di tutte le lettere maiuscole è quello di forzare tutte le lettere a legare durante il primo confronto impostandole tutte uguali <a>. Per assicurarsi che si ordinino in ordine alfabetico all'interno del caso, cambiare l'ultimo simbolo di fascicolazione dal IGNOREprimo simbolo di fascicolazione corrente. Seguendo questo schema, adiventerebbe:

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

A potrebbe diventare:

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

b potrebbe diventare:

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

B potrebbe diventare:

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

e così via per il resto delle lettere.

Dopo aver creato una versione personalizzata di iso14651_t1_common, segui le istruzioni nella risposta sopra collegata per compilare la tua localizzazione personalizzata.


6

L'impostazione LC_COLLATE=Cnon è sempre sufficiente per ordinare le lettere maiuscole prima di quelle minuscole. Potrebbe essere necessario impostare LC_ALL=C.

Ciò terrà conto anche dei caratteri non alfanumerici e persino non stampabili, ma se non si desidera che ci siano opzioni -de -i(descritto in man sort) per disattivarlo.

Probabilmente fallirà male con l'ingresso multibyte, come UTF-8 con caratteri non ASCII.

Per ottenere lettere minuscole (in ordine) prima di maiuscole (in ordine), il modo migliore in cui riesco a pensare che non comporta la rottura di un linguaggio di programmazione completo è invertire il caso di tutte le lettere prima dell'ordinamento e invertirle successivamente.

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

2

Non sono un esperto, ma non ho mai visto impostazioni locali che definiscono le regole di confronto in questo modo. AFAIK questo confronto è solo in C dove si basa su valori ASCII . (Normalmente lo risolverei semplicemente con una sceneggiatura.)

Tuttavia, non l'ho mai fatto, ma potresti voler guardare le pagine man localedef (1) e locale (5) per capire come sono definite le localizzazioni e alla fine definire la tua.

Inoltre, non dimenticare che se ci sono segni diacritici o caratteri speciali, la locale C non li tratterà come potresti volere. Ad esempio, non si áavvicina ao si Łavvicina L. In tali casi, la locale nativa della lingua sarebbe probabilmente un punto di partenza migliore.


0

Credo che la risposta sia senza la necessità di modificare LC_COLLATE (che significa lasciare la funzione come comportamento predefinito):

ordina il file -f

Questo funziona su Linux; si prega di fare riferimento alla sezione di aiuto per il comando nel caso in cui ci si trovi su Unix e si esegua una versione diversa. -f è definito come caso da ignorare.

Grazie per la correzione piuttosto (e stranamente) rapida e modifica alla grammatica fuori posto, Stephen Rauch.


-1
LC_COLLATE="en_US.UTF-8" sort file

Questo non ordina le lettere minuscole prima delle maiuscole? ideone.com/Gtyg4Z
iiSeymour,

Hmm, nel mio caso, ha fatto usando il tuo esempio.
Unxnut,

4
@unxnut Questo non è corretto. Senza il punto e virgola, il comando imposta l'ambiente per sort, ma con il punto e virgola la variabile è locale alla shell e non influisce sul comportamento di sort. Il punto e virgola potrebbe essere mantenuto come se anche la variabile fosse esportata, ma ciò influirebbe anche su altri comandi.
Anders Sjöqvist,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.