Какое Cзначение имеет для LC_ALLUnix-подобных систем?
Я знаю, что это требует одного и того же языка для всех аспектов, но что делает C?
Какое Cзначение имеет для LC_ALLUnix-подобных систем?
Я знаю, что это требует одного и того же языка для всех аспектов, но что делает C?
Ответы:
Это заставляет приложения использовать язык по умолчанию для вывода:
$ 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
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 от ato 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-совместимого awk( 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
В качестве примечания: ,десятичный разделитель конфликтует с ,арифметическим оператором, который может вызвать еще большую путаницу.
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's toupper(), dd conv=ucase...). Например:
grep -i i
не гарантируется совпадение Iв локали пользователя. В некоторых турецких районах , например, это делает не как верхний регистр iявляется İ(обратите внимание на точку) там и строчным Iесть ı(обратите внимание на недостающую точку).
¹ В зависимости от кодировки текста это не всегда правильно. Это справедливо для UTF-8 или однобайтовых наборов символов (например, iso-8859-1), но не обязательно для многобайтовых наборов не-UTF-8.
Например, если вы находитесь в 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 и A0x41 как в ASCII. Таким образом, наш LC_ALL=C grep '[a-zA-Z]'код будет соответствовать тем строкам, которые содержат эти символы, поскольку он будет неправильно интерпретировать эти последовательности байтов.
LC_COLLATE=C grep '[A-Za-z]'
будет работать, но только если LC_ALLне установлено иное (что переопределяет LC_COLLATE). Таким образом, вы можете в конечном итоге сделать:
grep '[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]'
если вы хотите искать английские буквы в файле, закодированном в кодировке локали.
Cлокаль требуется только для поддержки «переносимого набора символов» (ASCII 0-127), а поведение для символов> 127 технически не определено . На практике большинство программ будут обрабатывать их как непрозрачные данные и передавать их, как вы описали. Но не все: в частности, Ruby может подавить данные char с байтами> 127, если работает в Cлокали. Честно говоря, я не знаю, технически ли это «соответствует», но мы видели это в дикой природе .
perlи \x{7FFFFFFFFFFFFFFF}), и в то время как диапазон кодовых точек Unicode был произвольно ограничен U + 10FFFF (из-за ограничений конструкции UTF-16) некоторые инструменты по-прежнему распознают / генерируют 6-байтовые символы. Вот что я имел в виду под 6-байтовыми символами. В семантике Unix один символ - это одна кодовая точка. Ваши более чем одна кодовая точка «символы» чаще всего обозначаются как графемные кластеры для устранения неоднозначности символов.
Cэто локаль по умолчанию, "POSIX" это псевдоним "C". Я думаю, "C" является производным от ANSI-C. Возможно, ANSI-C определит локаль "POSIX".
Cимя локали происходит от "ANSI C".
Насколько я могу судить, 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 sortили GNU sort), но сначала в Ubuntu:
export LC_ALL=en_US.UTF-8;printf %s\\n ② ①|sort
Это печатает три строки в OS X (используя OS X sortили GNU sort), но одну строку в Ubuntu:
export LC_ALL=en_US.UTF-8;printf %b\\n \\u0d4c \\u0d57 \\u0d46\\u0d57|sort -u
Похоже, что он также 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
xclockwarning (Missing charsets in String to FontSet conversion), будет лучше, если вы будете использовать ее,LC_ALL=C.UTF-8чтобы избежать проблем с кириллицей. Чтобы установить эту переменную среды, вы должны добавить следующую строку в конец~/.bashrcфайла -export LC_ALL=C.UTF-8