Spécifiez l'ordre de tri avec LC_COLLATE pour que les minuscules soient avant les majuscules

16

Compte tenu du dossier:

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

Par défaut sort:

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

Avec LC_COLLATE=Cso triera en majuscule avant minuscule:

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

Est-il possible d'obtenir un tri pour inverser l'ordre des casse, c'est-à-dire les chiffres, en minuscules puis en majuscules?

iiSeymour
la source

Réponses:

8

Je ne connais aucun lieu qui, par défaut, trie dans cet ordre. La solution consiste à créer un environnement local personnalisé avec un ordre de tri personnalisé. Si quelqu'un, quatre ans plus tard, veut trier de façon personnalisée, voici l'astuce.

La grande majorité des paramètres régionaux ne spécifient pas leur propre ordre de tri, mais copient plutôt l'ordre de tri défini dans /usr/share/i18n/locales/iso14651_t1_commonafin que vous souhaitiez le modifier. Plutôt que de changer l'ordre de tri pour presque tous les paramètres régionaux en modifiant l'original iso14651_t1_common, je vous suggère de faire une copie. Des détails sur le fonctionnement de l'ordre de tri et sur la création de paramètres régionaux personnalisés dans votre $HOMErépertoire sans accès root se trouvent dans cette réponse à une question similaire .

Jetez un oeil à la façon dont aet Asont commandés en fonction de leurs entrées dans iso14651_t1_common:

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

bet Bsont similaires:

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

Nous voyons que lors de la première passe, les deux aet Aont le symbole d'assemblage <a>, tandis que les deux bet Bont le symbole d'assemblage <b>. Depuis <a>apparaît avant <b>dans iso14651_t1_common, aet Asont liés avant bet B. La deuxième passe ne rompt pas les liens car les quatre caractères ont le symbole d'assemblage <BAS>, mais pendant la troisième passe, les liens sont résolus car le symbole d'assemblage pour les lettres minuscules <MIN>apparaît à la ligne 3467, avant le symbole d'assemblage pour les lettres majuscules <CAP>(ligne 3488) . Ainsi , l'ordre de tri se termine comme a, A, b, B.

L'échange des premier et troisième symboles de classement trierait les lettres d'abord par casse (en bas puis en haut), puis par accent ( <BAS>signifie non accentué), puis par ordre alphabétique. Cependant , les deux <MIN>et <CAP>précédent les chiffres numériques, ce qui aurait pour effet indésirable de mettre des chiffres après les lettres.

La meilleure façon de garder les chiffres d' abord en faisant toutes les lettres minuscules viennent avant toutes les lettres majuscules est de forcer toutes les lettres à attacher au cours de la première comparaison en les plaçant tous égaux <a>. Pour vous assurer qu'ils sont triés par ordre alphabétique dans la casse, remplacez le dernier symbole d'assemblage par IGNOREle premier symbole d'assemblage actuel. Suivant ce modèle, adeviendrait:

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

A deviendrait:

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

b deviendrait:

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

B deviendrait:

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

et ainsi de suite pour le reste des lettres.

Une fois que vous avez créé une version personnalisée de iso14651_t1_common, suivez les instructions de la réponse liée ci-dessus pour compiler vos paramètres régionaux personnalisés.

beandip
la source
6

Le paramètre LC_COLLATE=Cn'est pas toujours suffisant pour trier les majuscules avant les minuscules. Vous devrez peut-être régler LC_ALL=C.

Cela prendra également en compte les caractères non alphanumériques et même non imprimables, mais si vous ne voulez pas qu'il y ait des options -det -i(décrit dans man sort) pour les désactiver.

Il échouera probablement mal avec une entrée multi-octets, comme UTF-8 avec des caractères non ASCII.

Pour obtenir des minuscules (dans l'ordre) avant les majuscules (dans l'ordre), la meilleure façon de penser que cela n'implique pas de sortir un langage de programmation à part entière est d'inverser la casse de toutes les lettres avant le tri, puis de les inverser. ensuite.

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

Je ne suis pas un expert mais je n'ai jamais vu de paramètres régionaux qui définissent le classement comme celui-ci. AFAIK ce classement est uniquement en C où il est basé sur des valeurs ASCII . (Normalement, je résoudrais simplement cela par un script.)

Cependant, je n'ai jamais fait cela, mais vous voudrez peut-être consulter les pages de manuel localedef (1) et locale (5) pour comprendre comment les paramètres régionaux sont définis et éventuellement définir la vôtre.

N'oubliez pas non plus que s'il y a des signes diacritiques ou des caractères spéciaux, les paramètres régionaux C ne les traiteront pas comme vous le souhaitez. Par exemple, il ne sera pas mis áprès aou Łprès L. Dans de tels cas, les paramètres régionaux natifs de la langue seraient probablement un meilleur point de départ.

Alois Mahdal
la source
0

Je pense que la réponse est sans que LC_COLLATE soit modifié (ce qui signifie laisser la fonction comme comportement par défaut):

trier le fichier -f

Cela fonctionne sous Linux; veuillez vous référer à votre section d'aide pour la commande au cas où vous êtes sous Unix et exécutez une version différente. -f est défini comme ignorant la casse.

Merci pour la correction rapide (et bizarrement) et la modification de la grammaire mal placée, Stephen Rauch.

1m.0g
la source
-1
LC_COLLATE="en_US.UTF-8" sort file
unnut
la source
Cela ne trie pas les minuscules avant les majuscules? ideone.com/Gtyg4Z
iiSeymour
Hmm, dans mon cas, c'est en utilisant votre exemple.
unxnut
4
@unxnut Ceci est incorrect. Sans le point-virgule, la commande définirait l'environnement pour sort, mais avec le point-virgule, la variable est locale au shell et n'affecte pas le comportement de sort. Le point-virgule peut être conservé tel quel si la variable est également exportée, mais cela affecte également les autres commandes.
Anders Sjöqvist