Влияние $ LANG на терминал

11

Я пытаюсь узнать, как $LANGпеременная ведет себя с gnome-терминал (и его параметр предпочтения кодировки символов). Я использовал iso8859-1 (latin1) в качестве основного набора символов, и все мои имена файлов закодированы как таковые.

Для следующих тестов я создам ls -lкаталог с испанскими символами в именах файлов:

Дело 1:

  • GNOME-терминал настроен для ISO-8859-1
  • LANG установить "en_US-iso8859-1"
  • Результат: я вижу все файлы правильно

Дело № 2:

  • gnome-терминал настроен на UTF-8
  • LANG установить "en_US-iso8859-1"
  • Результат: я вижу мусорные символы для всех испанских символов. Это ожидается, поскольку я изменил кодировку символов для терминала

Дело № 3:

  • GNOME-терминал настроен для ISO-8859-1
  • LANG установить на "en_US-UTF-8"
  • Результат: я вижу мусорные символы для всех испанских символов.

Почему в этом последнем случае я вижу искаженные символы? Разве вывод ls не должен отправлять имена файлов прямо на gnome-терминал, как они есть? И поскольку gnome-терминал настроен на ISO-8859-1, я ожидал, что они будут выглядеть правильно.

На мгновение я подумал, что, возможно, возможно, bash рассматривает мою $LANGпеременную и выполняет какое-то преобразование. Затем я переключил свой терминал на UTF-8, но я все еще не могу видеть символы правильно. Я даже передал вывод ls в xxd и, к своему удивлению, все еще вижу файлы, закодированные в том виде, как они есть: ISO-8859-1.

В заключение: если мой список содержит символы ISO-8859-1 и мой эмулятор терминала настроен на ту же кодировку символов: кто выполняет преобразование, если LANGустановлено иное?

Спасибо за любую помощь, которую вы можете предоставить.

Craconia

Craconia
источник

Ответы:

5

Ваши настройки LANGдолжны совпадать с настройками терминала. Точнее, ваши настройки для LC_CTYPE(кодировки символов) должны совпадать с кодировкой терминала, другие настройки локали не должны совпадать. И кодировка терминала обычно определяется опцией эмулятора терминала, а не переменной языка. Комбинация LC_CTYPEобъединяет два указания: оно сообщает приложениям, какую кодировку использовать на терминале (как для ввода, так и для вывода), и оно сообщает приложениям, какую кодировку использовать с файлами. В случаях 2 и 3 вы сказали lsотображать вывод в кодировке, отличной от кодировки терминала, поэтому вывод искажается.

Если вы работаете с кодировками UTF-8 и latin-1 в разное время, настройте терминал на использование UTF-8. Это должно заставить его установить LC_CTYPEзначение, указывающее UTF-8; не переопределяйте этот параметр. (Если эмулятор терминала не установлен LC_CTYPE, переопределите его в файле запуска оболочки или для всего сеанса.) Для работы с данными latin-1 в терминале UTF-8 используйте luit(входит в комплект утилит X).

LC_CTYPE=en_US.iso88591 luit

(Вы можете использовать любую другую локаль с той же кодировкой, например LC_CTYPE=es_ES.iso88591 luit.)

Жиль "ТАК - прекрати быть злым"
источник
Спасибо Жилю за это замечательное объяснение, особенно за объяснение двух показаний для LC_CTYPE.
Craconia
Возвращаясь к моему последнему случаю: я подумал, что, поскольку все имена файлов были закодированы в латинице 1 плюс тот факт, что мое конечное устройство вывода, которое создавало глифы (мой терминал), также было настроено для латиницы 1, я ожидал, что файлы будут видны правильно (независимо от LC_CTYPE) ...
Craconia
Мне никогда не приходило в голову, что он lsбудет рассматривать LC_CTYPE (в данном случае установлено UTF-8) и будет выполнять какую-то проверку набора символов: всякий раз, когда он видит что-то, не совместимое с набором символов, он будет выплевывать определенный символ (например, "? «). Я сказал «проверка», потому что она не будет выполнять «преобразование», как это делает luit. Это так?
Craconia
@Craconia В третьем случае lsзаменяет непечатные символы на ?. Большинство строк, закодированных в латинском-1, которые представляют реальные слова, имеют непечатаемые символы, если интерпретируются как UTF-8.
Жиль "ТАК - перестать быть злым"
5

В случае № 2 и № 3 вы смешиваете две разные кодировки UTF-8 и Latin-1. В случае № 1 вы используете Latin-1 для обоих, так что у вас нет проблем.

Команда ls(и все другие программы с хорошим поведением) используют настройку LANG для определения кодировки .

Вы можете смешивать два разных языка, но вы не должны смешивать два разных кодирования .

Убедитесь, что переменные среды LC_ * также используют ту же кодировку, что и ваша переменная LANG.

Как правило, в настоящее время вы должны настроить свою систему на использование только UTF-8.

Если вам нужно отредактировать устаревшие файлы данных (например, свойства java), вы должны либо использовать специализированный редактор (например, java ide), либо обеспечить кодирование такими инструментами, как iconvили `recode ..

Х.-Дирк Шмитт
источник
Спасибо. Да, у меня есть планы перейти на UTF-8 в ближайшее время. Получил кучу имен файлов для конвертации плюс много много текстовых файлов. iconv & convmv на помощь ...
Craconia
0

Это может быть за пределами вашей необходимости, но ....

Оказывается, в RHEL5, и, вероятно, ранее многие справочные страницы каким-то образом по какой-то предопределенной причине были как-то осознаны. То есть необработанная man-страница была преобразована из своего собственного набора символов в 7-битный ASCII. Независимо от того, что вы делаете с LC и LANG, страница руководства для пользователя latin1создает страницу руководства, которая фактически бесполезна. Все специальные (8-битные) символы внутри были заменены на 7-битные заполнители (обычно ??). Я нахожу это смешным.

Но utf8версия этих справочных страниц может существовать в каталоге для конкретного языка. Хитрость заключается в том, чтобы попросить их по имени. Например, latin1 на самом деле iso_8859-1. Если вы сделаете на нем справочную страницу и ваши настройки LANG верны, вы увидите, что ожидаете; Страница man находится в специфическом для языка subdir ( en/man7/iso_8859-1.7). Но если вы по iso-8859-1какой-то причине попросите , вы получите версию ASCII.

Otheus
источник