Что делает “LC_ALL=C”?

Я нашел решение здесь. Это рекомендует создать новый компактный стиль GTK путем вставки этого в ~/.gtkrc-2.0:

style "gtkcompact" {
GtkButton::default_border={0,0,0,0}
GtkButton::default_outside_border={0,0,0,0}
GtkButtonBox::child_min_width=0
GtkButtonBox::child_min_heigth=0
GtkButtonBox::child_internal_pad_x=0
GtkButtonBox::child_internal_pad_y=0
GtkMenu::vertical-padding=1
GtkMenuBar::internal_padding=0
GtkMenuItem::horizontal_padding=4
GtkToolbar::internal-padding=0
GtkToolbar::space-size=0
GtkOptionMenu::indicator_size=0
GtkOptionMenu::indicator_spacing=0
GtkPaned::handle_size=4
GtkRange::trough_border=0
GtkRange::stepper_spacing=0
GtkScale::value_spacing=0
GtkScrolledWindow::scrollbar_spacing=0
GtkTreeView::vertical-separator=0
GtkTreeView::horizontal-separator=0
GtkTreeView::fixed-height-mode=TRUE
GtkWidget::focus_padding=0
}
class "GtkWidget" style "gtkcompact"

336
22.08.2013, 10:37
6 ответов

Это вынуждает приложения использовать язык по умолчанию для вывода:

$ LC_ALL=es_ES man
¿Qué página de manual desea?

$ LC_ALL=C man
What manual page do you want?

и сортировка сил для байта:

$ LC_ALL=en_US sort <<< $'a\nb\nA\nB'
a
A
b
B

$ LC_ALL=C sort <<< $'a\nb\nA\nB'
A
B
a
b
216
27.01.2020, 19:26
  • 1
    +1 для хорошего exemples, но испытывает недостаток в важной информации, которые находятся на ответе Stephane... –  Olivier Dulac 22.08.2013, 14:06
  • 2
    Что Вы подразумеваете под языком по умолчанию? –  Stéphane Chazelas 10.09.2014, 17:59
  • 3
    Да, я понимаю, что автор может сделать то, что он любит включая не, делают то, что это говорит относительно олова. Вещь. Американский английский язык является единственным языком, который может быть представлен правильно с набором символов в LC_ALL=C, единственный язык, где порядок сортировки в LC_ALL=C (LC_COLLATE) имеет смысл, LC_ALL=C (LC_TIME), имеет английские имена месяца и дня. Я никогда не видел приложения, куда LC_ALL=C возвратил сообщение на другом языке от LC_ALL=en LANGUAGE=en. Таким образом, я наделен правом сообщить об ошибке против программы если это не так? (не говорящий о приложениях, не переведенных в английский язык здесь). –  Stéphane Chazelas 10.09.2014, 22:55
  • 4
    Проблемой является "американский английский язык, единственный язык, который может быть представлен правильно с набором символов в LC_ALL=C". Это обычно только верно в программах C/C++ при использовании узких символов, но даже затем существуют исключения (так как существует несколько языков, которые только используют символы и символы, найденные в ASCII). Сообщение об ошибке, когда язык по умолчанию не будет английским, заставит Вас казаться... фанатичными. –  Ignacio Vazquez-Abrams 11.09.2014, 01:37
  • 5
    Обратите внимание, что на английском языке (значение LANG=en_US.utf8) сообщения могут (и если) используют unicode символы такой в качестве “” для заключения в кавычки строк. Принимая во внимание, что в LANG=C, это только имеет ASCII (двойные кавычки, одинарные левые кавычки и апострофы). спасибо –  Ángel 10.03.2015, 18:55

LC_ALL переменная среды, которая переопределяет все другие настройки локализации (кроме $LANGUAGE при некоторых обстоятельствах).

Различные аспекты локализаций (как тысяча разделителя или символа десятичной точки, набора символов, порядка сортировки, месяц, дневные имена, язык или сообщения приложения как сообщения об ошибках, обозначение денежной единицы) могут быть установлены с помощью нескольких переменных среды.

Вы будете обычно устанавливать $LANG к Вашему предпочтению со значением, которое определяет Ваш регион (как fr_CH.UTF-8 если Вы находитесь во франкоязычной Швейцарии, с помощью UTF-8). Человек LC_xxx переменные переопределяют определенный аспект. LC_ALL переопределяет их всех. locale команда при вызове без аргумента дает сводку текущих настроек.

Например, в системе GNU, я добираюсь:

$ locale
LANG=en_GB.UTF-8
LANGUAGE=
LC_CTYPE="en_GB.UTF-8"
LC_NUMERIC="en_GB.UTF-8"
LC_TIME="en_GB.UTF-8"
LC_COLLATE="en_GB.UTF-8"
LC_MONETARY="en_GB.UTF-8"
LC_MESSAGES="en_GB.UTF-8"
LC_PAPER="en_GB.UTF-8"
LC_NAME="en_GB.UTF-8"
LC_ADDRESS="en_GB.UTF-8"
LC_TELEPHONE="en_GB.UTF-8"
LC_MEASUREMENT="en_GB.UTF-8"
LC_IDENTIFICATION="en_GB.UTF-8"
LC_ALL=

Я могу переопределить отдельную установку с, например:

$ LC_TIME=fr_FR.UTF-8 date
jeudi 22 août 2013, 10:41:30 (UTC+0100)

Или:

$ LC_MONETARY=fr_FR.UTF-8 locale currency_symbol
€

Или переопределите все с LC_ALL.

$ LC_ALL=C LANG=fr_FR.UTF-8 LC_MESSAGES=fr_FR.UTF-8 cat /
cat: /: Is a directory

В сценарии, если Вы хотите вызвать определенную установку, поскольку Вы не знаете то, что настройки пользователь вызвали (возможно LC_ALL также), Ваше лучшее, самое безопасное и обычно только опция состоит в том, чтобы вызвать LC_ALL.

C локаль является специальной локалью, которая предназначена, чтобы быть самой простой локалью. Вы могли также сказать, что, в то время как другие локали для людей, локаль C для компьютеров. В локали C символы являются единственными байтами, набором символов является ASCII (хорошо, не требуется, чтобы, но на практике будет в системах, которые большинство из нас будет когда-либо получать для использования), порядок сортировки основан на значениях байта, язык является обычно американским английским языком (хотя для сообщений приложения (в противоположность вещам как имена месяца или дня или сообщения системными библиотеками), это на усмотрение автора приложения), и вещи как обозначения денежной единицы не определяются.

В некоторых системах существует различие с локалью POSIX, где, например, порядок сортировки для символов неASCII не определяется.

Вы обычно выполняете команду с LC_ALL=C для предотвращения настроек пользователя для вмешательства в сценарий. Например, если Вы хотите [a-z] соответствовать 26 символам ASCII от a кому: z, необходимо установить LC_ALL=C.

В системах GNU, LC_ALL=C и LC_ALL=POSIX (или LC_MESSAGES=C|POSIX) переопределение $LANGUAGE, в то время как LC_ALL=anything-else не был бы.

Несколько случаев, где обычно необходимо устанавливать LC_ALL=C:

  • sort -u или sort ... | uniq.... Во многих локалях кроме C, в некоторых системах (особенно GNU), некоторые символы имеют тот же порядок сортировки. sort -u не сообщают уникальные строки, но одна из каждой группы строк, которые имеют равный порядок сортировки. Таким образом, если Вы действительно хотите уникальные строки, Вам нужна локаль, где символы являются байтом, и все символы имеют другой порядок сортировки (который C гарантии локали).
  • то же относится = оператор совместимого POSIX expr или == оператор совместимого POSIX awks (mawk и gawk не POSIX в том отношении), которые не проверяют, идентичны ли две строки, но сортируют ли они то же.
  • Диапазоны символов как в grep. Если Вы означаете соответствовать букве на языке пользователя, использовать grep '[[:alpha:]]' и не изменяйте LC_ALL. Но если Вы хотите соответствовать a-zA-Z Символы ASCII, Вам нужно также LC_ALL=C grep '[[:alpha:]]' или LC_ALL=C grep '[a-zA-Z]'¹. [a-z] соответствует символам тот вид после a и прежде z (хотя со многими API это более сложно, чем это). В других локалях Вы обычно не знаете, каково это. Например, некоторые локали игнорируют регистр для сортировки так [a-z] в некоторых API как bash шаблоны, мог включать [B-Z] или [A-Y]. Во многих локалях UTF-8 (включая en_US.UTF-8 в большинстве систем), [a-z] будет включать латинские буквы от a кому: y с диакритическими знаками, но не теми z (так как z виды перед ними), который я не могу вообразить, был бы тем, что Вы хотите (почему был бы Вы хотеть включать é и нет ź?).
  • арифметика с плавающей точкой в ksh93. ksh93 почести decimal_point начинание LC_NUMERIC. Если Вы пишете сценарий, который содержит a=$((1.2/7)), это прекратит работать, когда выполнено пользователем, локаль которого имеет запятую как десятичный разделитель:

    $ ksh93 -c 'echo $((1.1/2))'
    0.55
    $ LANG=fr_FR.UTF-8  ksh93 -c 'echo $((1.1/2))'
    ksh93: 1.1/2: arithmetic syntax error
    

    Затем Вам нужны вещи как:

    #! /bin/ksh93 -
    float input="$1" # get it as input from the user in his locale
    float output
    arith() { typeset LC_ALL=C; (($@)); }
    arith output=input/1.2 # use the dot here as it will be interpreted
                           # under LC_ALL=C
    echo "$output" # output in the user's locale
    

    Как примечание стороны: , десятичный разделитель конфликтует с , арифметический оператор, который может вызвать еще больше беспорядка.

  • Когда Вам нужны символы, чтобы быть байтами. В наше время большинство локалей является UTF-8, базирующимся, что означает, что символы могут поднять от 1 до 6 байтов. При контакте с данными, которые предназначены, чтобы быть байтами с текстовыми утилитами, Вы захотите установить LC_ALL=C. Это также значительно улучшит производительность, потому что парсинг данные UTF-8 имеет стоимость.
  • заключение предыдущей точки: когда обработка текста, где Вы не знаете то, в чем записан набор символов вход, но может предположить, что это совместимо с ASCII (как фактически, все наборы символов). Например, grep '<.*>' искать строки, содержащие a <, > пара не будет никакая работа, если Вы будете в локали UTF-8, и вход кодируется в однобайтовом 8-разрядном наборе символов как iso8859-15. Поэтому . только символы соответствий и символы неASCII в iso8859-15 вероятны не сформировать допустимый символ в UTF-8. С другой стороны, LC_ALL=C grep '<.*>' будет работать, потому что любое значение байта формирует допустимый символ в C локаль.
  • Любое время, где Вы обрабатываете входные данные или выходные данные, который не предназначается от человека. Если Вы говорите с пользователем, можно хотеть использовать их конвенцию и язык, но например, если Вы генерируете некоторые числа для питания некоторого другого приложения, которое ожидает, англичане разрабатывают десятичные точки или английские имена месяца, Вы захотите установить LC_ALL=C:

    $ printf '%g\n' 1e-2
    0,01
    $ LC_ALL=C printf '%g\n' 1e-2
    0.01
    $ date +%b
    août
    $ LC_ALL=C date +%b
    Aug
    

    Это также относится к вещам как нечувствительное к регистру сравнение (как в grep -i) и замена регистра (awk toupper(), dd conv=ucase...). Например:

    grep -i i
    

    как гарантируют, не будет соответствовать на I в локали пользователя. В некоторых турецких локалях, например, это не делает как верхний регистр i İ (отметьте точку), там и нижний регистр I ı (отметьте недостающую точку).


¹ В зависимости от кодирования текста, это - не обязательно правильный поступок все же. Это допустимо для UTF-8 или однобайтовых наборов символов (как iso-8859-1), но не обязательно non-UTF-8 многобайтовые наборы символов.

Например, если Вы находитесь в a zh_HK.big5hkscs локаль (Гонконг, с помощью Гонконгского варианта китайской кодировки символов BIG5), и Вы хотите искать английские буквы в файле, закодированном в этом наборы символов, делая также:

LC_ALL=C grep '[[:alpha:]]'

или

LC_ALL=C grep '[a-zA-Z]'

было бы неправильным, потому что в том наборе символов (и многие другие, но едва используемый, так как UTF-8 вышел), много символов содержит байты, которые соответствуют кодированию ASCII символов A-Za-z. Например, весь из A䨝䰲丕乙乜你再劀劈呸哻唥唧噀噦嚳坽 (и намного больше), содержат кодирование A. 0x96 0x41, и A 0x41 как в ASCII. Так наш LC_ALL=C grep '[a-zA-Z]' соответствовал бы на тех строках, которые содержат те символы, поскольку это неправильно истолковало бы те последовательности байтов.

LC_COLLATE=C grep '[A-Za-z]'

работал бы, но только если LC_ALL иначе не установлен (который переопределил бы LC_COLLATE). Таким образом, можно закончить тем, что имели необходимость сделать:

grep '[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]'

если Вы хотели искать английские буквы в файле, закодированном в кодировании локали.

348
27.01.2020, 19:26
  • 1
    +1, это - лучший ответ (для указания на переопределение, и т.д.). Но испытывает недостаток в (хороших) примерах ^^ –  Olivier Dulac 22.08.2013, 14:08
  • 2
    несовершеннолетний придирается к мелочам: C локаль только требуется, чтобы поддерживать "переносимый набор символов" (ASCII 0-127), и поведение для символов> 127 является технически неуказанным. На практике большинство программ будет рассматривать их как непрозрачные данные и передавать их через, как Вы описали. Но не все: в частности, Ruby может дросселировать на символьных данных с байтами> 127 при выполнении в C локаль. Я честно не знаю, "совместимо" ли это технически, но мы видели его в дикой природе. –  Andrew Janke 16.12.2015, 21:26
  • 3
    @AndrewJanke, да. Обратите внимание, что переносимый набор символов не делает события, подразумевают ASCII, ни 0-127. Было большое обсуждение списка рассылки группы Остина на том, чем свойства "C" набора символов локали были бы и общее согласие (и это будет разъяснено в следующей спецификации), то, что тот набор символов был бы однобайтовым, и охватил бы полный диапазон на 8 битов (со свойствами, описанными здесь). Тем временем да может быть некоторое расхождение (как ошибка или потому что спецификация не является достаточно явной). В anycase LC_ALL=C является самым близким, можно получить нормальное поведение. –  Stéphane Chazelas 16.12.2015, 22:11
  • 4
    кодовая точка Unicode в UTF-8, может иметь максимум 4 октетов (или байты), но для некоторого Символа нужна более затем одна кодовая точка, которая может привести к более длинным последовательностям, чем 6 октетов. –  12431234123412341234123 18.04.2017, 20:15
  • 5
    @12431234123412341234123, исходные UTF-8 encoding покрытия до U+7FFFFFFF (6 байтов, и существуют некоторые расширения для подхождения к 13 байтам как perl \x{7FFFFFFFFFFFFFFF}) и в то время как диапазон кодовых точек Unicode был произвольно ограничен U+10FFFF (из-за ограничения дизайна UTF-16), некоторые инструменты все еще распознают/производят 6-байтовые символы. Это - то, что я подразумевал под 6-байтовыми символами. В семантике Unix один символ является одной кодовой точкой. На Вашу больше чем одну кодовую точку "символы" в более общем плане ссылаются как кластеры графемы для устранения неоднозначности от символов. –  Stéphane Chazelas 18.04.2017, 20:42

C локаль по умолчанию, "POSIX" является псевдонимом "C". Я предполагаю, что "C" получен от ANSI-C. Возможно, ANSI-C определяет локаль "POSIX".

8
27.01.2020, 19:26
  • 1
    И C и UNIX безусловно предшествуют ANSI C. –  a CVn 22.08.2013, 13:55
  • 2
    @MichaelKjörling: Так? Я видел документацию перед ANSI, и она не имела локалей. Внутренне в AT&T Bell Labs, все говорили на английском языке. –  MSalters 22.08.2013, 17:50
  • 3
    @MSalters то, что документация перед ANSI для языка C не упоминает локали (который может или не может подразумевать, что предварительный ANSI, C не имел никакого понятия локалей; в конце концов, я вполне уверен, язык все еще не делает, но это не относится к делу), не подразумевает что C имя локали происходит из "ANSI C". –  a CVn 23.08.2013, 00:18
  • 4
    @MichaelKjörling: Вы упускаете суть. Когда локали уже были представлены, "C" предназначенный "ANSI C". То, что это означало, что K&R C в прошлом не важен. –  MSalters 23.08.2013, 10:36

Насколько я могу судить, OS X использует порядок сортировки кодовых точек в локали UTF-8, поэтому это исключение из некоторых пунктов, упомянутых в ответе Стефана Чазеласа.

Это напечатает 26 в OS X и 310 в Ubuntu:

export LC_ALL=en_US.UTF-8
printf %b $(printf '\\U%08x\\n' $(seq $((0x11)) $((0x10ffff))))|grep -a '[a-z]'|wc -l

Приведенный ниже код ничего не печатает в OS X, указывая на то, что ввод отсортирован. Шесть удаляемых суррогатных символов вызывают ошибку недопустимой последовательности байтов.

export LC_ALL=en_US.UTF-8
for ((i=1;i<=0x1fffff;i++));do
  x=$(printf %04x $i)
  [[ $x = @(000a|d800|db7f|db80|dbff|dc00|dfff) ]]&&continue
  printf %b \\U$x\\n
done|sort -c

Приведенный ниже код ничего не печатает в OS X, указывая на то, что нет двух последовательных кодовых точек (по крайней мере, между U + 000B и U + D7FF) с одинаковым порядком сопоставления.

export LC_ALL=en_US.UTF-8
for ((i=0xb;i<=0xd7fe;i++));do
  printf %b $(printf '\\U%08x\\n' $((i+1)) $i)|sort -c 2>/dev/null&&echo $i
done

(В приведенных выше примерах используется % b , потому что printf \\ U25 приводит к ошибке в zsh.)

Некоторые символы и последовательности символов имеют одинаковый порядок сортировки в системах GNU не имеют такого же порядка сортировки в OS X. В OS X сначала печатается ① (с использованием сортировки OS X или GNU ), но ② сначала в Ubuntu:

export LC_ALL=en_US.UTF-8;printf %s\\n ② ①|sort

Это печатает три строки в OS X (с использованием сортировки OS X или GNU sort ), но одну строку в Ubuntu:

export LC_ALL=en_US.UTF-8;printf %b\\n \\u0d4c \\u0d57 \\u0d46\\u0d57|sort -u
4
27.01.2020, 19:26

Похоже, что LC_COLLATE также управляет «алфавитным порядком», используемым ls. Локаль США будет отсортирована следующим образом:

a.C
aFilename.C
aFilename.H
a.H

в основном игнорирует точки. Вы можете предпочесть:

a.C
a.H
aFilename.C
aFilename.H

Конечно, люблю. Установка LC_COLLATE на C выполняет это. Обратите внимание, что он также будет сортировать строчные буквы после всех заглавных:

A.C
A.H
AFilename.C
a.C
a.H
4
27.01.2020, 19:26

В качестве дополнения к ответу Абрамса @Ignacio Vazquez -для некоторых выходных данных консоли требуется определить масштаб сеанса, но не локальный масштаб.

Например,

Как он упоминает,в большинстве случаев так оно и работает

$ man
What manual page do you want?
$ LC_ALL=es_ES man
Qupina de manual desea?

Однако в некоторых случаях не работает

$ LC_ALL=es_ES cpio
-bash: /usr/bin/cpio: Permission denied

Поэтому вместо этого вам нужно сделать это

$ export LC_ALL=es_ES
$ cpio
-bash: /usr/bin/cpio: Permiso denegado

Затем возвращает его обратно на английский язык, если это необходимо

$ export LC_ALL=C
$ cpio
-bash: /usr/bin/cpio: Permission denied

Также обратите внимание, что для некоторых не алфавитных -языков вам лучше добавить «.UTF -8», как упоминают другие.

Например, для японского языка

$ export LC_ALL=ja_JP
$ cpio
-bash: /usr/bin/cpio: Ĥ

$ export LC_ALL=ja_JP.UTF-8
$ cpio
-bash: /usr/bin/cpio: 許可がありません
1
07.11.2021, 01:53

Теги

Похожие вопросы