Określ kolejność sortowania za pomocą LC_COLLATE, aby małe litery były przed dużymi

16

Biorąc pod uwagę plik:

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

Domyślnie sort:

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

Z LC_COLLATE=Ctak będą sortowane w wielkiej litery przed małymi literami:

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

Czy można uzyskać sort, aby odwrócić kolejność liter, to znaczy cyfry, małe i wielkie litery?

iiSeymour
źródło

Odpowiedzi:

8

Nie znam żadnych ustawień narodowych, które domyślnie sortują w tej kolejności. Rozwiązaniem jest utworzenie niestandardowych ustawień regionalnych z niestandardowym porządkiem sortowania. Jeśli ktoś, cztery lata później, chce sortować w niestandardowy sposób, oto sztuczka.

Zdecydowana większość ustawień narodowych nie określa własnego porządku sortowania, ale raczej kopiuje zdefiniowany porządek sortowania, /usr/share/i18n/locales/iso14651_t1_commonabyś to właśnie chciał edytować. Zamiast zmieniać porządek sortowania dla prawie wszystkich ustawień regionalnych poprzez modyfikację oryginału iso14651_t1_common, sugeruję, aby wykonać kopię. Szczegółowe informacje o tym, jak działa porządek sortowania i jak utworzyć niestandardowe ustawienia narodowe w $HOMEkatalogu bez dostępu użytkownika root, znajdują się w tej odpowiedzi na podobne pytanie .

Zobacz, jak ai Asą uporządkowane na podstawie ich wpisów w iso14651_t1_common:

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

bi Bsą podobne:

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

Widzimy, że na pierwszym przejeździe, zarówno ai Amają symbol zestawiania <a>, podczas gdy zarówno bi Bmają symbol zestawiania <b>. Ponieważ <a>pojawia się przed <b>w iso14651_t1_common, ai Asą związani przed bi B. Drugi przebieg nie zrywa więzi, ponieważ wszystkie cztery znaki mają symbol zestawiania <BAS>, ale podczas trzeciego przejścia remisy są rozwiązywane, ponieważ symbol zestawienia małych liter <MIN>pojawia się w linii 3467, przed symbolem zestawiania wielkich liter <CAP>(linia 3488) . Zatem porządek kończy jako a, A, b, B.

Zamiana pierwszego i trzeciego zestawionego symbolu posortowałaby litery najpierw według wielkości liter (najpierw niższa niż górna), następnie według akcentu ( <BAS>czyli bez akcentu), a następnie według kolejności alfabetycznej. Jednakże , zarówno <MIN>i <CAP>przyjść przed cyfr, więc byłoby to mieć niepożądany wpływ wprowadzenie cyfry po literami.

Najłatwiejszym sposobem, aby cyfry były pierwsze, a wszystkie małe litery pojawiały się przed wszystkimi dużymi literami, jest wymuszenie wiązania wszystkich liter podczas pierwszego porównania, ustawiając je wszystkie na równe <a>. Aby upewnić się, że sortują alfabetycznie według wielkości liter, zmień ostatni symbol zestawiania z IGNOREna bieżący pierwszy symbol zestawiania. Zgodnie z tym wzorem astałoby się:

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

A stanie się:

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

b stanie się:

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

B stanie się:

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

i tak dalej dla pozostałych liter.

Po utworzeniu dostosowanej wersji iso14651_t1_commonpostępuj zgodnie z instrukcjami w odpowiedzi powyżej, aby skompilować niestandardowe ustawienia regionalne.

beandip
źródło
6

Ustawienie LC_COLLATE=Cnie zawsze wystarcza do sortowania wielkich liter przed małymi. Może być konieczne ustawienie LC_ALL=C.

Będzie to również uwzględniać znaki niealfanumeryczne, a nawet niedrukowalne, ale jeśli nie chcesz, aby były dostępne opcje -di -i(opisane w man sort), to je wyłączy.

Prawdopodobnie zawiedzie to przy wprowadzaniu danych wielobajtowych, takich jak UTF-8 ze znakami spoza ASCII.

Aby uzyskać małe litery (w kolejności) przed dużymi literami (w kolejności), najlepszym sposobem, w jaki mogę to wymyślić, nie wymaga wyodrębnienia pełnoprawnego języka programowania jest odwrócenie wielkości liter wszystkich liter przed sortowaniem i odwrócenie ich z powrotem potem.

tr 'a-zA-Z' 'A-Za-z' < file | LC_ALL=C sort | tr 'a-zA-Z' 'A-Za-z'
Law29
źródło
2

Nie jestem ekspertem, ale nigdy nie widziałem ustawień regionalnych, które definiują takie sortowanie. AFAIK to zestawienie jest tylko w C, gdzie jest oparte na wartościach ASCII . (Normalnie rozwiązałbym to po prostu za pomocą skryptu).

Jednak nigdy tego nie robiłem, ale możesz zajrzeć na strony podręcznika localedef (1) i locale (5), aby zrozumieć, w jaki sposób są zdefiniowane ustawienia narodowe i ostatecznie zdefiniować własne.

Nie zapominaj również, że jeśli są jakieś znaki diakrytyczne lub znaki specjalne, ustawienia regionalne C nie będą traktować ich tak, jak chcesz. Na przykład nie będzie się ázbliżać aani Łzbliżać L. W takich przypadkach natywna lokalizacja języka jest prawdopodobnie lepszym punktem wyjścia.

Alois Mahdal
źródło
0

Uważam, że odpowiedź nie wymaga zmiany LC_COLLATE (co oznacza pozostawienie funkcji jako domyślnego zachowania):

sortuj plik -f

Działa to w systemie Linux; zapoznaj się z sekcją pomocy dotyczącą polecenia, jeśli korzystasz z Uniksa i używasz innej wersji. -f jest zdefiniowane jako ignorowanie wielkości liter.

Dzięki za (raczej dziwną) szybką poprawkę i edycję niewłaściwej gramatyki, Stephena Raucha.

1m.0g
źródło
-1
LC_COLLATE="en_US.UTF-8" sort file
unxnut
źródło
To nie sortuje małych liter przed dużymi? ideone.com/Gtyg4Z
iiSeymour
Hmm, w moim przypadku zrobiło to na twoim przykładzie.
unxnut
4
@unxnut To jest nieprawidłowe. Bez średnika polecenie ustawiłoby środowisko sort, ale w przypadku średnika zmienna jest lokalna dla powłoki i nie wpływa na zachowanie sort. Średnik można zachować tak, jak gdyby zmienna została również wyeksportowana, ale wpłynęłoby to również na inne polecenia.
Anders Sjöqvist,