Do czego służy C
wartość LC_ALL
w systemach uniksopodobnych?
Wiem, że wymusza to to samo ustawienie regionalne dla wszystkich aspektów, ale co robi C
?
environment-variables
locale
jcubic
źródło
źródło
xclock
ostrzeżeniem (Missing charsets in String to FontSet conversion
), lepiej będzie, jeśli użyjesz go,LC_ALL=C.UTF-8
aby uniknąć problemów z cyrylicą. Aby ustawić tę zmienną środowiskową, musisz dodać następujący wiersz na końcu~/.bashrc
pliku -export LC_ALL=C.UTF-8
Odpowiedzi:
Zmusza aplikacje do używania domyślnego języka danych wyjściowych:
i wymusza sortowanie bajtowe:
źródło
LC_ALL
to zmienna środowiskowa, która zastępuje wszystkie pozostałe ustawienia lokalizacji ( z wyjątkiem$LANGUAGE
niektórych okoliczności ).Różne aspekty lokalizacji (takie jak separator tysięcy lub znak dziesiętny, zestaw znaków, kolejność sortowania, miesiąc, nazwy dni, komunikaty językowe lub aplikacji, takie jak komunikaty o błędach, symbol waluty) można ustawić za pomocą kilku zmiennych środowiskowych.
Zazwyczaj ustawiasz
$LANG
preferencje za pomocą wartości identyfikującej twój region (np.fr_CH.UTF-8
Jeśli jesteś w francuskojęzycznej Szwajcarii, używając UTF-8). PoszczególneLC_xxx
zmienne przesłaniają pewien aspekt.LC_ALL
zastępuje je wszystkie.locale
Poleceń, gdy wywołana bez argumentów przedstawia podsumowanie aktualnych ustawieniach.Na przykład w systemie GNU otrzymuję:
Mogę zastąpić indywidualne ustawienie, na przykład:
Lub:
Lub zastąp wszystko za pomocą LC_ALL.
W skrypcie, jeśli chcesz wymusić określone ustawienie, ponieważ nie wiesz, jakie ustawienia wymusił użytkownik (prawdopodobnie również LC_ALL), najlepszą, najbezpieczniejszą i ogólnie jedyną opcją jest wymuszenie LC_ALL.
Lokalizacja
C
jest specjalną lokalizacją, która ma być najprostszą lokalizacją. Można również powiedzieć, że podczas gdy inne ustawienia narodowe są przeznaczone dla ludzi, ustawienia regionalne C dotyczą komputerów. W ustawieniach regionalnych C znaki są jednobajtowe, zestaw znaków to ASCII (cóż, nie jest to wymagane, ale w praktyce będzie w systemach, z których większość z nas będzie mogła korzystać), kolejność sortowania jest oparta na wartościach bajtów, język jest zwykle w języku angielskim (chociaż w przypadku komunikatów aplikacji (w przeciwieństwie do nazw takich jak nazwy miesięcy lub dni lub wiadomości w bibliotekach systemowych), zależy to od autora aplikacji), a symbole walut nie są zdefiniowane.W niektórych systemach występuje różnica w ustawieniach regionalnych POSIX, w których na przykład nie zdefiniowano kolejności sortowania znaków spoza ASCII.
Zazwyczaj uruchamiasz polecenie z LC_ALL = C, aby uniknąć ustawień użytkownika, które mogłyby zakłócać twój skrypt. Na przykład, jeśli chcesz
[a-z]
dopasować 26 znaków ASCII oda
doz
, musisz ustawićLC_ALL=C
.W systemach GNU
LC_ALL=C
iLC_ALL=POSIX
(lubLC_MESSAGES=C|POSIX
) zastępuj$LANGUAGE
, podczas gdyLC_ALL=anything-else
nie.Kilka przypadków, w których zwykle musisz ustawić
LC_ALL=C
:sort -u
lubsort ... | uniq...
. W wielu lokalizacjach innych niż C, w niektórych systemach (zwłaszcza GNU), niektóre znaki mają tę samą kolejność sortowania .sort -u
nie zgłasza unikalnych wierszy, ale jeden z każdej grupy wierszy o jednakowej kolejności sortowania. Jeśli więc chcesz mieć unikalne wiersze, potrzebujesz ustawień regionalnych, w których znaki są bajtami, a wszystkie znaki mają inną kolejność sortowania (coC
gwarantuje ustawienie regionalne).=
operatora zgodnego z POSIXexpr
lub==
operatora zgodnego z POSIXawk
(mawk
igawk
nie są pod tym względem POSIX), które nie sprawdzają, czy dwa ciągi są identyczne, ale czy sortują to samo.grep
. Jeśli chcesz dopasować literę w języku użytkownika, używajgrep '[[:alpha:]]'
i nie modyfikujLC_ALL
. Ale jeśli chcesz, aby dopasowaća-zA-Z
znaki ASCII, trzeba alboLC_ALL=C grep '[[:alpha:]]'
czyLC_ALL=C grep '[a-zA-Z]'
¹.[a-z]
dopasowuje znaki, które sortują poa
i przedz
(choć w przypadku wielu interfejsów API jest to bardziej skomplikowane). W innych lokalizacjach zazwyczaj nie wiesz, co to są. Na przykład niektóre ustawienia narodowe ignorują wielkość liter podczas sortowania, więc[a-z]
w niektórych interfejsach API, takich jakbash
wzorce, może zawierać[B-Z]
lub[A-Y]
. W wielu lokalizacjach UTF-8 (w tymen_US.UTF-8
w większości systemów)[a-z]
będą zawierać litery łacińskie oda
doy
z znakami diakrytycznymi, ale nie tez
(odz
sortuje przed nimi), czego nie wyobrażam sobie, co byś chciał (dlaczego chcesz to uwzględnić,é
a nieź
?).arytmetyka zmiennoprzecinkowa w
ksh93
.ksh93
honorujedecimal_point
ustawienie wLC_NUMERIC
. Jeśli napiszesz skrypt, który zawieraa=$((1.2/7))
, przestanie on działać po uruchomieniu przez użytkownika, którego ustawienia regionalne mają przecinek jako separator dziesiętny:Potrzebujesz więc takich rzeczy jak:
Na marginesie:
,
separator dziesiętny,
powoduje konflikt z operatorem arytmetycznym, co może powodować jeszcze większe zamieszanie.grep '<.*>'
aby wyszukać wiersze zawierające a<
,>
para nie będzie działać, jeśli jesteś w ustawieniach regionalnych UTF-8, a dane wejściowe są zakodowane w jednym bajcie 8-bitowym zestawie znaków, takim jak iso8859-15. Jest tak, ponieważ.
tylko znaki pasujące i znaki spoza ASCII w iso8859-15 prawdopodobnie nie tworzą prawidłowego znaku w UTF-8. Z drugiej stronyLC_ALL=C grep '<.*>'
zadziała, ponieważ każda wartość bajtu tworzy poprawny znak wC
ustawieniach regionalnych.Za każdym razem, gdy przetwarzasz dane wejściowe lub wyjściowe, które nie są przeznaczone dla / dla człowieka. Jeśli rozmawiasz z użytkownikiem, możesz chcieć użyć jego konwencji i języka, ale na przykład, jeśli wygenerujesz pewne liczby, aby nakarmić inną aplikację, która oczekuje kropek dziesiętnych w stylu angielskim lub nazw angielskich miesięcy, możesz ustaw LC_ALL = C:
Dotyczy to również takich rzeczy, jak porównanie bez rozróżniania wielkości liter (jak w
grep -i
) i konwersja wielkości liter (awk
'stoupper()
,dd conv=ucase
...). Na przykład:nie gwarantuje się, że dopasuje się
I
w ustawieniach regionalnych użytkownika. Na przykład w niektórych tureckich ustawieniach regionalnych nie jest to tak, że wielkie literyi
są tamİ
(zwróć uwagę na kropkę), a małe literyI
toı
(zauważ brakującą kropkę).¹ W zależności od kodowania tekstu niekoniecznie jest to jednak właściwe. Dotyczy to zestawów znaków UTF-8 lub jednobajtowych (takich jak iso-8859-1), ale niekoniecznie zestawów znaków wielobajtowych innych niż UTF-8.
Na przykład, jeśli korzystasz z
zh_HK.big5hkscs
ustawień regionalnych (Hongkong, korzystasz z wariantu Hongkongu chińskiego kodowania znaków BIG5) i chcesz poszukać angielskich liter w pliku zakodowanym w tych zestawach znaków, wykonując:lub
byłoby błędne, ponieważ w tym zestawie znaków (i wielu innych, ale rzadko używanych od czasu pojawienia się UTF-8), wiele znaków zawiera bajty odpowiadające kodowaniu ASCII znaków A-Za-z. Na przykład wszystkie
A䨝䰲丕乙乜你再劀劈呸哻唥唧噀噦嚳坽
(i wiele innych) zawierają kodowanieA
.䨝
to 0x96 0x41 iA
0x41 jak w ASCII. Zatem naszeLC_ALL=C grep '[a-zA-Z]'
pasowałyby do tych wierszy, które zawierają te znaki, ponieważ błędnie interpretują te sekwencje bajtów.działałoby, ale tylko wtedy, gdy
LC_ALL
nie jest inaczej ustawione (co zastąpiłobyLC_COLLATE
). Więc możesz skończyć z koniecznością:jeśli chcesz poszukać angielskich liter w pliku zakodowanym w kodowaniu ustawień regionalnych.
źródło
C
regionalne są wymagane tylko do obsługi „przenośnego zestawu znaków” (ASCII 0-127), a zachowanie znaków> 127 jest technicznie nieokreślone . W praktyce większość programów traktuje je jako nieprzejrzyste dane i przekazuje je zgodnie z opisem. Ale nie wszystkie: w szczególności Ruby może zadławić się danymi char o bajtach> 127, jeśli działa wC
ustawieniach narodowych. Naprawdę nie wiem, czy to technicznie „zgodne”, ale widzieliśmy to na wolności .perl
„s\x{7FFFFFFFFFFFFFFF}
), a gdy zakres unikodowe punktów kod został dowolnie ograniczony U + 10FFFF (z powodu ograniczeń projektowych UTF-16), niektóre narzędzia nadal rozpoznają / tworzą 6-bajtowe znaki. To właśnie miałem na myśli 6 bajtowych znaków. W semantyce uniksowej jeden znak jest jednym punktem kodowym. Twoje więcej niż jeden punkt kodowy „znaki” są bardziej ogólnie określany jako klastry graphem disambiguate z postaciami.C
to domyślne ustawienie narodowe, „POSIX” to alias „C”. Chyba „C” pochodzi od ANSI-C. Może ANSI-C zdefiniuje ustawienia regionalne „POSIX”.źródło
C
nazwa ustawień regionalnych pochodzi od „ANSI C”.O ile mogę stwierdzić, OS X używa porządku sortowania punktów kodowych w ustawieniach regionalnych UTF-8, więc jest to wyjątek od niektórych punktów wymienionych w odpowiedzi Stéphane Chazelas.
Wypisuje 26 w OS X i 310 w Ubuntu:
Poniższy kod nie drukuje nic w OS X, co wskazuje, że dane wejściowe są posortowane. Sześć usuniętych znaków zastępczych powoduje błąd niedozwolonej sekwencji bajtów.
Poniższy kod nie drukuje nic w OS X, co wskazuje, że nie ma dwóch kolejnych punktów kodu (przynajmniej między U + 000B i U + D7FF), które mają tę samą kolejność sortowania.
(W powyższych przykładach użyto,
%b
ponieważprintf \\U25
powoduje błąd w zsh.)Niektóre znaki i sekwencje znaków, które mają tę samą kolejność sortowania w systemach GNU, nie mają tej samej kolejności sortowania w OS X. Spowoduje to wydrukowanie ① najpierw w OS X (używając OS X
sort
lub GNUsort
), ale ② najpierw w Ubuntu:Spowoduje to wydrukowanie trzech linii w systemie OS X (przy użyciu systemu OS X
sort
lub GNUsort
), ale jednej linii w systemie Ubuntu:źródło
Wygląda na to, że
LC_COLLATE
kontroluje również „kolejność alfabetyczną” używaną przez ls. Ustawienia regionalne w USA będą sortowane w następujący sposób:w zasadzie ignorując kropki. Może wolisz:
Na pewno tak. Ustawienie
LC_COLLATE
doC
osiągnięcia tego. Zauważ, że sortuje również małe litery po wszystkich wielkich literach:źródło