[A-Z]
w bash
dopasowuje wszystkie elementy zestawiające (znaki, ale wywołanie może być również ciągiem znaków jak Dsz
w węgierskich ustawieniach regionalnych), które sortują po, A
a sortują przed Z
. W twoim regionie c
prawdopodobnie sortuje się pomiędzy B i C.
$ printf '%s\n' A a á b B c C Ç z Z Ẑ | sort
a
A
á
b
B
c
C
Ç
z
Z
Ẑ
Tak c
lub z
byłoby pasować [A-Z]
, ale nie Ẑ
lub a
.
$ printf '%s\n' A a á b B c C Ç z Z Ẑ |
pipe> bash -c 'while IFS= read -r x; do case $x in [A-Z]) echo "$x"; esac; done'
A
á
b
B
c
C
Ç
z
Z
W ustawieniach regionalnych C kolejność byłaby następująca:
$ printf '%s\n' A a á b B c C Ç z Z Ẑ | LC_COLLATE=C sort
A
B
C
Z
a
b
c
z
Ç
á
Ẑ
Więc [A-Z]
będzie pasować A
, B
, C
, Z
, ale nie Ç
i nadal nie Ẑ
.
Jeśli chcesz dopasować wielkie litery (w dowolnym skrypcie), możesz użyć [[:upper:]]
zamiast tego. Nie ma wbudowanego sposobu, bash
aby dopasowywać tylko wielkie litery w skrypcie łacińskim (z wyjątkiem listowania ich indywidualnie).
Jeśli chcesz, aby dopasować A
się do Z
angielskich liter bez znaków diakrytycznych, można użyć [A-Z]
albo [[:upper:]]
ale w C
regionie (przy założeniu, że dane nie są kodowane w zestawach znaków, takich jak BIG5 lub GB18030 który ma kilka znaków, których kodowanie zawiera kodowanie tych liter) lub listy je indywidualnie ( [ABCDEFGHIJKLMNOPQRSTUVWXYZ]
).
Zauważ, że istnieją pewne różnice między powłokami.
For zsh
, bash -O globasciiranges
(dziwnie nazwana opcja wprowadzona w bash-4.3) schily-sh
i yash
, [A-Z]
pasuje do znaków, których punkt kodowy znajduje się między tym A
a tym Z
, więc byłoby to równoważne zachowaniu bash
w ustawieniach regionalnych C.
Dla popiołu, mksza i starożytnych pocisków, takich samych jak zsh
powyżej, ale ograniczonych do jednobajtowych zestawów znaków. Oznacza to, że na przykład w ustawieniach regionalnych UTF-8 [É-Ź]
nie pasowałoby Ó
, ale ponieważ tak [<c3><89>-<c5><b9>]
, pasowałyby do wartości bajtów 0x89 do 0xc5!
ksh93
zachowuje się tak bash
, ale traktuje jako zakresy przypadków specjalnych, których końce zaczynają się małymi lub dużymi literami. W takim przypadku dopasowuje się tylko w elementach zestawiających, które sortują między tymi końcami, ale które (lub ich pierwszy znak w przypadku elementów zestawiających wiele znaków) są również pisane małymi literami (lub odpowiednio dużymi literami). Więc [A-Z]
nie będzie pasować É
, ale nie na e
jak e
robi porządek między A
a Z
, ale nie jest wielka, jak A
i Z
.
W przypadku fnmatch()
wzorców (jak w find -name '[A-Z]'
) lub systemowych wyrażeń regularnych (jak w grep '[A-Z]'
) zależy to od systemu i ustawień regionalnych. Na przykład w systemie GNU tutaj [A-Z]
nie pasuje x
w en_GB.UTF-8
ustawieniach regionalnych, ale w tym th_TH.UTF-8
jednym. Nie jest dla mnie jasne, jakich informacji używa, aby to ustalić, ale najwyraźniej opiera się na tabeli odnośników pochodzącej z danych regionalnych LC_COLLATE ).
Wszystkie zachowania są dozwolone przez POSIX, ponieważ POSIX pozostawia zachowanie zakresów nieokreślonych w ustawieniach regionalnych innych niż ustawienia regionalne C. Teraz możemy spierać się o zalety każdego podejścia.
bash
Podejście to ma wiele sensu [C-G]
, ponieważ chcemy, aby postacie były pomiędzy C
a G
. I stosując porządek użytkownika za to, co określa, co w międzyczasie jest najbardziej logicznym rozwiązaniem.
Problem polega na tym, że przełamuje oczekiwania wielu ludzi, zwłaszcza tych, którzy przywykli do tradycyjnego zachowania przed Unicode, nawet dni poprzedzających internacjonalizację. Choć od normalnego użytkownika, to sprawia, maja poczucie, że [C-I]
zawiera h
jako h
list jest między C
a I
i że [A-g]
nie obejmuje Z
, to inna sprawa dla osób mających do czynienia z ASCII tylko przez dziesięciolecia.
To bash
zachowanie różni się również od [A-Z]
dopasowania zakresu w innych narzędziach GNU, takich jak wyrażenia regularne GNU (jak w grep
/ sed
...) lub fnmatch()
jak w find -name
.
Oznacza to również, że to, co [A-Z]
pasuje, różni się w zależności od środowiska, systemu operacyjnego i wersji systemu operacyjnego. Fakt, że [A-Z]
pasuje do Á, ale nie Ź, jest również nieoptymalny.
Dla zsh
/ yash
używamy innego porządku sortowania. Zamiast polegać na pojęciu kolejności znaków przez użytkownika, używamy wartości kodu punktu znakowego. Ma to tę zaletę, że jest łatwe do zrozumienia, ale z praktycznego punktu widzenia niewielu, poza ASCII, nie jest bardzo przydatne. [A-Z]
dopasowuje 26 wielkich amerykańskich liter w języku amerykańskim, [0-9]
dopasowuje cyfry dziesiętne. Istnieją punkty kodowe w Unicode, które są zgodne z kolejnością niektórych alfabetów, ale nie są uogólnione i nie mogą być uogólnione, ponieważ w każdym razie różni ludzie używający tego samego skryptu niekoniecznie zgadzają się na kolejność liter.
W przypadku tradycyjnych powłok i mksh, myślnik jest zepsuty (teraz, gdy większość ludzi używa znaków wielobajtowych), ale przede wszystkim dlatego, że nie ma jeszcze obsługi wielu bajtów. Dodanie obsługi wielu bajtów do powłok takich jak bash
i zsh
było dużym wysiłkiem i wciąż trwa. yash
(japońska powłoka) od samego początku była projektowana z obsługą wielu bajtów.
Podejście ksh93 ma tę zaletę, że jest spójne z wyrażeniami regularnymi systemu lub fnmatch () (lub przynajmniej wydaje się, że przynajmniej w systemach GNU). Nie łamie to oczekiwań niektórych osób, ponieważ [A-Z]
nie zawiera małych liter, [A-Z]
obejmuje É
(i Á, ale nie Ź). To nie jest zgodne z sort
lub ogólnie strcoll()
zamówienie.
locale
wynik? Nie mogę tego odtworzyć (touch foo; echo [A-Z]*
wypisuje dosłowny wzorzec, a nie „foo”, w innym pustym katalogu).