Что делает «CL_ALL = C»?

Что делает C значение для LC_ALL в Unix-подобных системах?

Я знаю, что он заставляет ту же локаль для всех аспектов, но что делает C?

249 голосов | спросил jcubic 22 AM000000110000003731 2013, 11:32:37

5 ответов


162

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

$ LC_ALL = es_ES man
¿Quà © página de manual desea?
$ LC_ALL = C человек
Какую страницу руководства вы хотите?
$ LC_ALL = en_US sort <<<$ «А \ пь \ нА \ пв»


б
В
$ LC_ALL = C sort <<$ «А \ пь \ нА \ пв»

В

б
ответил Ignacio Vazquez-Abrams 22 AM000000110000003731 2013, 11:41:37
258

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

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

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

Например, в системе GNU я получаю:

$ locale
ЛАНГ = 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: /: является ли каталог

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

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

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

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

В системах GNU LC_ALL = C и LC_ALL = POSIX (или LC_MESSAGES = C | POSIX) переопределить $ LANGUAGE, а LC_ALL = ничего-else не будет.

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

  • sort -u или sort ... | уник .... Во многих локалях, отличных от C, на некоторых системах (особенно в GNU), некоторые символы имеют одинаковый порядок сортировки . sort -u не сообщает уникальные строки, а одну из каждой группы строк, которые имеют равный порядок сортировки. Поэтому, если вам нужны уникальные строки, вам нужна локаль, где символы являются байтами, а все символы имеют разный порядок сортировки (что гарантирует языковой стандарт C).
  • то же самое относится к оператору = для POSIX-совместимого expr или == оператора POSIX-совместимого awk s (mawk и gawk) не являются POSIX в этом отношении), которые не проверяют, идентичны ли две строки, независимо от того, сортируют ли они то же самое.
  • Диапазоны символов, например, в grep. Если вы хотите совместить букву на языке пользователя, используйте grep '[[: alpha:]]' и не изменяйте LC_ALL. Но если вы хотите совместить символы ASCII a-zA-Z, вам нужно либо LC_ALL = C grep '[[: alpha:]]', либо LC_ALL = C grep '[a-zA-Z]' ¹. [a-z] соответствует символам, которые сортируются после a и до z (хотя со многими API-интерфейсами это сложнее). В других местах вы вообще не знаете, что это такое. Например, некоторые локали игнорируют регистр для сортировки, поэтому [az] в некоторых API, например bash, может включать [BZ] или [ AY]. Во многих локалях UTF-8 (включаяen_US.UTF-8 в большинстве систем), [az] будет включать латинские буквы от 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: арифметическая синтаксическая ошибка
    

    Тогда вам понадобятся такие вещи, как:

    #! /bin /ksh93 -
    float input = "$ 1" # получить его как вход от пользователя в его локали
    выход поплавка
    arith () {typeset LC_ALL = C; (($ @)); }
    arith output = input /1.2 # здесь используется здесь, поскольку он будет интерпретироваться
                           # под LC_ALL = C
    echo "$ output" # output в локали пользователя
    

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

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

    $ printf '% g \ n' 1e-2
    0,01
    $ LC_ALL = C printf '% g \ n' 1e-2
    0,01
    $ date +% b
    AOA »т
    $ LC_ALL = C date +% b
    август
    

    Это также относится к таким ситуациям, как нечувствительность к регистру (например, в grep -i) и преобразование case (awk '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, а A - 0x41, как в ASCII. Таким образом, наш LC_ALL = C grep '[a-zA-Z]' будет совпадать на тех строках, которые содержат эти символы, так как он неверно интерпретирует эти последовательности байтов.

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

будет работать, но только если LC_ALL в противном случае не установлен (что бы переопределить LC_COLLATE)). Поэтому вам может понадобиться сделать:

grep '[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]'

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

ответил Stéphane Chazelas 22 PM00000010000000731 2013, 13:50:07
3

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

a.C
aFilename.C
aFilename.H
хиджры

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

a.C
хиджры
aFilename.C
aFilename.H

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

A.C
хиджры
AFilename.C
a.C
хиджры
ответил SteveInCO 12 +03002016-10-12T03:41:24+03:00312016bEurope/MoscowWed, 12 Oct 2016 03:41:24 +0300 2016, 03:41:24
3

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

ответил Edward Shen 22 AM000000110000001031 2013, 11:37:10
2

Насколько я могу судить, OS X использует порядок сортировки кодовой точки в локалях UTF-8, поэтому он является исключением из некоторых пунктов, упомянутых в ответе Stà © phane Chazelas.

Это отображает 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
для ((i = 1; i <= 0x1fffff; i ++)); do
  x = $ (printf% 04x $ i)
  [[$ x = @ (000a | d800 | db7f | db80 | dbff | dc00 | dfff)]] & & продолжить
  printf% b \\ U $ x \\ n
done | sort -c

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

 export LC_ALL = en_US.UTF-8
для ((i = 0xb; i <= 0xd7fe; i ++)); do
  printf% b $ (printf '\\ U% 08x \\ n' $ ((i + 1)) $ i) | sort -c 2> /dev /null & & echo $ i
сделанный

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

Некоторые символы и последовательности символов, которые имеют один и тот же порядок сортировки в системах GNU, не имеют одинакового порядка сортировки в OS X. Это печатает «сначала в OS X (используя либо код OS X или GNU sort), но сначала â'¡ в Ubuntu:

 export LC_ALL = en_US.UTF-8; printf% s \\ n â'¡ â '| сортировать

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

 export LC_ALL = en_US.UTF-8; printf% b \\ n \\ u0d4c \\ u0d57 \\ u0d46 \\ u0d57 | sort -u
ответил user4669748 7 Maypm16 2016, 18:22:48

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132