Wpływ $ LANG na terminal

11

Próbuję dowiedzieć się, jak $LANGzachowuje się zmienna z gnome-terminalem (i opcją preferencji kodowania znaków). Używam iso8859-1 (latin1) jako mojego głównego zestawu znaków i wszystkie moje nazwy plików są zakodowane jako takie.

Dla następujących testów zrobię ls -lkatalog z hiszpańskimi znakami akcentowanymi w nazwach plików:

Przypadek 1:

  • terminal gnome skonfigurowany dla ISO-8859-1
  • LANG ustawiono na „en_US-iso8859-1”
  • Wynik: poprawnie widzę wszystkie pliki

Przypadek nr 2:

  • terminal gnome skonfigurowany dla UTF-8
  • LANG ustawiono na „en_US-iso8859-1”
  • Wynik: widzę śmieciowe znaki dla wszystkich hiszpańskich znaków. Jest to oczekiwane, ponieważ zmieniłem kodowanie znaków dla terminala

Przypadek nr 3:

  • terminal gnome skonfigurowany dla ISO-8859-1
  • LANG ustawiono na „en_US-UTF-8”
  • Wynik: widzę śmieciowe znaki dla wszystkich hiszpańskich znaków.

Dlaczego w tym ostatnim przypadku widzę zniekształcone postacie? Czy wyjście ls nie powinno wysyłać nazw plików prosto do terminala gnome? A ponieważ terminal gnome jest skonfigurowany dla ISO-8859-1, oczekiwałbym, że będą wyglądać dobrze.

Przez chwilę myślałem, że być może bash rozważa moją $LANGzmienną i dokonuje konwersji. Potem zmieniłem terminal na UTF-8, ale nadal nie widzę poprawnie znaków. Nawet potokowałem wyjście ls do xxd i ku mojemu zdziwieniu wciąż widzę pliki zakodowane takimi, jakie są: ISO-8859-1.

Podsumowując: Jeśli mój wpis zawiera znaki ISO-8859-1, a emulator terminala jest skonfigurowany do tego samego kodowania znaków: Kto dokonuje konwersji, jeśli LANGjest inaczej?

Dzięki za wszelką pomoc, którą możesz udzielić.

Craconia

Craconia
źródło

Odpowiedzi:

5

Twoje ustawienie dla LANGmusi być zgodne z terminalem. Mówiąc dokładniej, twoje ustawienie LC_CTYPE(kodowanie znaków) musi być zgodne z kodowaniem terminala, inne ustawienia regionalne nie muszą być zgodne. Kodowanie terminala jest zwykle określane przez opcję emulatora terminala, a nie przez zmienną lokalizacji. Że LC_CTYPEłączy dwa wskaźniki: co mówi aplikacje kodujące do użytku terminal (zarówno na wejściu i wyjściu), a to co mówi aplikacje kodujące do korzystania z plików. W przypadkach 2 i 3 kazano lswyświetlać dane wyjściowe w kodowaniu innym niż kodowanie terminala, więc dane wyjściowe są zniekształcone.

Jeśli pracujesz zarówno z kodowaniem UTF-8, jak i latin-1 w różnych momentach, skonfiguruj swój terminal, aby używał UTF-8. Powinno to spowodować ustawienie LC_CTYPEgo na wartość wskazującą UTF-8; nie zastępuj tego ustawienia. (Jeśli emulator terminala nie jest ustawiony LC_CTYPE, zastąp go w pliku startowym powłoki lub przez całą sesję.) Aby pracować z danymi Latin-1 w terminalu UTF-8, użyj luit(zawartego w pakiecie narzędzi X).

LC_CTYPE=en_US.iso88591 luit

(Możesz użyć dowolnego innego ustawienia narodowego z tym samym kodowaniem, np LC_CTYPE=es_ES.iso88591 luit.)

Gilles „SO- przestań być zły”
źródło
Dzięki Gilles za wspaniałe wyjaśnienie, szczególnie za wyjaśnienie dwóch wskazań dla LC_CTYPE.
Craconia
Wracając do mojej ostatniej sprawy: pomyślałem, że ponieważ wszystkie nazwy plików zostały zakodowane w Latin1 oraz fakt, że moje końcowe urządzenie wyjściowe, to, które tworzy glify (mój terminal), zostało również skonfigurowane dla Latin1, spodziewałem się, że zobaczę pliki poprawnie (niezależnie od LC_CTYPE) ...
Craconia
Nigdy nie przyszło mi do głowy, lsże bierze pod uwagę LC_CTYPE (w tym przypadku ustawiony na UTF-8) i dokonuje pewnego rodzaju sprawdzania poprawności zestawu znaków: ilekroć widzi coś niezgodnego z zestawem znaków, wypluwa określony znak (np. „? „). Powiedziałem „walidacja”, ponieważ nie wykona „konwersji”, jak to robi Luit. Czy to tak jest?
Craconia
@Craconia W trzecim przypadku lszastępuje znaki niedrukowalne przez ?. Większość łańcuchów kodowanych w łacińskim-1, które reprezentują prawdziwe słowa, mają znaki niedrukowalne, jeśli są interpretowane jako UTF-8.
Gilles „SO- przestań być zły”
5

W przypadku # 2 i # 3 miksujesz dwa różne kodowania UTF-8 i Latin-1. W przypadku nr 1 używasz Latin-1 dla obu, więc nie masz problemu.

lsPolecenie (i wszystkich innych Programms dobrze zachowujących się) używać ustawień Lang, określenia kodowania .

Możesz miksować dwa różne języki, ale nie powinieneś mieszać dwóch różnych kodowań .

Upewnij się, że zmienne środowiskowe LC_ * również używają tego samego kodowania, co zmienna LANG.

Zasadniczo należy dziś skonfigurować system tak, aby korzystał tylko z UTF-8.

Jeśli musisz edytować staromodne pliki danych (np. Właściwości Java), powinieneś albo użyć specjalistycznego edytora (np. Java) lub zapewnić kodowanie za pomocą narzędzi takich jak iconvlub `recode ..

H.-Dirk Schmitt
źródło
Dzięki. Tak, mam plany przejścia na UTF-8 w najbliższej przyszłości. Mam sporo nazw plików do konwersji oraz wiele plików tekstowych. iconv i convmv na ratunek ...
Craconia
0

To może być poza twoją potrzebą, ale ...

Okazuje się, że w RHEL5, i prawdopodobnie wcześniej, wiele stron podręcznika zostało z jakiegoś powodu z jakiegoś powodu zapomnianych przez gd. Oznacza to, że nieprzetworzona strona podręcznika została przekonwertowana z natywnego zestawu znaków na 7-bitowy kod ASCII. Bez względu na to, co robisz z LC i LANG, strona podręcznika użytkownikalatin1 tworzy która jest faktycznie bezużyteczna. Wszystkie znaki specjalne (8-bitowe) zostały zastąpione 7-bitowymi symbolami zastępczymi (zwykle ??). Uważam to za zabawne.

Ale utf8wersja tych stron podręcznika może istnieć w katalogu specyficznym dla języka. Sztuka polega na tym, aby poprosić o nie po imieniu. Na przykład latin1 jest w rzeczywistości iso_8859-1. Jeśli zrobisz na nim stronę man, a twoje ustawienia LANG są prawidłowe, zobaczysz, czego oczekujesz; strona man znajduje się w specyficznym dla języka subdir ( en/man7/iso_8859-1.7). Ale jeśli iso-8859-1z jakiegoś powodu poprosisz o to , otrzymasz wersję ASCII.

Otheus
źródło