C
LC_ALL
Unix 계열 시스템에서 의 가치는 어떤 역할을 합니까?
나는 그것이 모든 측면에서 동일한 로케일을 사용하도록 강제한다는 것을 알고 있지만 그것이 무엇을 합니까 C
?
답변1
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을 강제하는 것입니다.
locale은 C
특별한 로케일이며, 가장 간단한 로케일입니다. 다른 로케일은 인간용이고 C 로케일은 컴퓨터용이라고 말할 수도 있습니다. C 로케일에서 문자는 단일 바이트이고 문자 세트는 ASCII(물론 필수는 아니지만 실제로 우리 대부분이 사용하는 시스템에 있을 것임)이며 정렬 순서는 바이트 값 1을 기반으로 하며 언어는 일반적으로 미국 영어입니다(애플리케이션 메시지의 경우(월이나 일 이름 또는 시스템 라이브러리의 메시지와 반대) 애플리케이션 작성자의 재량에 따라 다름) 통화 기호와 같은 것은 정의되지 않습니다.
일부 시스템에서는 비ASCII 문자에 대한 정렬 순서가 정의되지 않는 등 POSIX 로케일과 차이가 있습니다.
일반적으로 사용자 설정이 스크립트를 방해하지 않도록 하려면 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 호환 연산자 (awk
해당 문제는 POSIXmawk
아님 ) 에도 동일하게 적용됩니다 .gawk
. 와 같은 문자 범위를
grep
사용자 언어의 문자와 일치시키려면 를 사용grep '[[:alpha:]]'
하고 수정하지 마세요LC_ALL
. 그러나 ASCII 문자를 일치시키려면 or² 이a-zA-Z
필요합니다 . 전후 에 정렬된 문자 와 일치합니다(많은 API의 경우 상황이 이보다 더 복잡하지만). 다른 지역에서는 그것이 무엇인지 모르는 경우가 많습니다. 예를 들어 일부 로케일은 정렬 시 대/소문자를 무시하므로 일부 API(예: 스키마)에서는 또는 를 포함할 수 있습니다. 많은 UTF-8 로케일(대부분의 시스템 포함)에는 분음 부호가 있는 to부터의 라틴 문자가 포함되지만 분음 부호가 있는 문자는 포함되지 않습니다(그 이전에). 이것이 여러분이 원하는 것일 것이라고는 상상할 수 없습니다. 포함시키나요?)LC_ALL=C grep '[[:alpha:]]'
LC_ALL=C grep '[a-zA-Z]'
[a-z]
a
z
[a-z]
bash
[B-Z]
[A-Y]
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 호환이라고 가정할 수 있습니다(거의 모든 문자 세트의 경우와 마찬가지로). 예를 들어, UTF-8 로케일에 있고 입력이 단일 바이트 8비트 문자 세트(예: iso8859-15)로 인코딩된 경우 , 쌍이
grep '<.*>'
포함된 행을 찾는 것은<
작동하지 않습니다. iso8859-15에서 일치하는 문자, 비ASCII 문자만 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
이는 대소문자를 구분하지 않는 비교(예: in ) 및 대소문자 변환( awk
's toupper()
, ...) 에도 적용됩니다 dd conv=ucase
. 예를 들어:
grep -i i
I
사용자 로케일의 일치는 보장되지 않습니다. 예를 들어, 일부 터키어 로케일에서는 대문자 i
( İ
점 참고) 및 소문자 I
( ı
누락된 점 참고) 처럼 보이지 않습니다 .
노트
다시 말하지만 이는 ASCII 기반 시스템(대부분의 시스템)에서만 작동합니다. POSIX strcoll()
에서는 C 로케일의 === 최적화를 허용하지 않는 EBCDIC 시스템에서도 C 로케일의 조합 순서가 ASCII 문자 세트의 문자 순서가 되도록 요구합니다 .strcmp()
² 텍스트 인코딩에 따라 이것이 반드시 올바른 접근 방식이 아닐 수도 있습니다. 이는 UTF-8 또는 단일 바이트 문자 집합(예: iso-8859-1)에 작동하지만 UTF-8이 아닌 멀티바이트 문자 집합에는 반드시 그런 것은 아닙니다.
예를 들어, 특정 지역(BIG5 중국어 문자 인코딩의 홍콩 변형을 사용하는 홍콩)에 있고 zh_HK.big5hkscs
해당 문자 세트로 인코딩된 파일에서 영어 문자를 찾으려는 경우 다음 중 하나를 수행합니다.
LC_ALL=C grep '[[:alpha:]]'
또는
LC_ALL=C grep '[a-zA-Z]'
해당 문자 세트(및 기타 많은 문자 세트(UTF-8 출현 이후 거의 사용되지 않음))에 많은 문자가 포함되어 있기 때문에 잘못된 것입니다.포함하다A-Za-z 문자에 해당하는 ASCII로 인코딩된 바이트입니다. 예를 들어 . 를 A䨝䰲丕乙乜你再劀劈呸哻唥唧噀噦嚳坽
포함하는 모든 것(및 그 이상) 은 0x96 0x41이며 이는 ASCII와 마찬가지로 0x41입니다. 따라서 이러한 바이트 시퀀스를 잘못 해석할 수 있으므로 이러한 문자가 포함된 행을 일치시킵니다.A
䨝
A
LC_ALL=C grep '[a-zA-Z]'
LC_COLLATE=C grep '[A-Za-z]'
작동하지만 LC_ALL
달리 설정하지 않은 경우에만 가능합니다(이 값이 재정의됨 LC_COLLATE
). 따라서 결국 다음을 수행해야 할 수도 있습니다.
grep '[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]'
로케일 인코딩으로 인코딩된 파일에서 영문자를 찾고 싶다면.
3 일부 사람들은 이제 유니코드 코드 포인트(및 UTF-8 데이터를 인코딩/디코딩하는 라이브러리)가 코드 포인트 U+0000 ~ U+10FFFF(0xD800 ~ 0xDFFF 제외)로 임의로 제한되었으므로 길이가 1 ~ 1이라고 주장합니다. UTF-16 인코딩을 수용하기 위해 U+7FFFFFFF부터 4바이트가 필요하지만 일부 애플리케이션에서는 여전히 6바이트 UTF-8 시퀀스(0xD800 .. 0xDFFF 범위에 속하는 시퀀스 포함)를 인코딩/디코딩할 수 있습니다.
답변2
이는 애플리케이션이 출력에 기본 언어를 사용하도록 강제합니다.
$ 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
답변3
C
은 기본 로캘이고 "POSIX"는 "C"의 별칭입니다. "C"는 ANSI-C에서 파생된 것 같습니다. 아마도 ANSI-C는 "POSIX" 로케일을 정의할 수도 있습니다.
답변4
또한 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