유닉스 계열 시스템 의 C
가치는 무엇입니까 LC_ALL
?
나는 그것이 모든 측면에서 동일한 로케일을 강요한다는 것을 알고 있지만 무엇을 C
합니까?
유닉스 계열 시스템 의 C
가치는 무엇입니까 LC_ALL
?
나는 그것이 모든 측면에서 동일한 로케일을 강요한다는 것을 알고 있지만 무엇을 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 문자를에서 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
들 ( mawk
및 gawk
두 개의 스트링이 동일한 지 확인하지만 그들은 동일한 정렬 여부를하지 않는 점에서 POSIX되지 않는다).grep
. 사용자 언어로 된 글자를 일치 시키려면를 사용 grep '[[:alpha:]]'
하고 수정하지 마십시오 LC_ALL
. 그러나 a-zA-Z
ASCII 문자 를 일치 시키려면 LC_ALL=C grep '[[:alpha:]]'
또는 LC_ALL=C grep '[a-zA-Z]'
¹ 이 필요합니다 . 많은 API를 사용하면 그보다 더 복잡하지만 이전과 [a-z]
이후에 정렬되는 문자와 일치합니다 . 다른 로케일에서는 일반적으로 이것이 무엇인지 모릅니다. 예를 들어 일부 로케일 그렇게 정렬하는 경우를 무시 과 같은 몇 가지의 API에 포함 할 수있다, 패턴 또는 . 많은 UTF-8 로켈에서 (를 포함하여 대부분의 시스템에서), 라틴어에서 편지가 포함됩니다 에 분음 부호하지만의 사람들을 (이후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
참고로 ,
소수점 구분 기호는 ,
산술 연산자 와 충돌하여 더 많은 혼란을 초래할 수 있습니다.
grep '<.*>'
포함하는 라인을 찾아 <
, >
쌍을 것입니다 당신이 UTF-8 로켈에서하고있어 입력이 ISO8859-15 같은 한 싱글 바이트 8 비트 문자로 인코딩 된 경우 어떤 작업. 때문 .
만은 문자 및 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
)과 대소 문자 변환 ( awk
의 toupper()
, dd conv=ucase
...). 예를 들어 :
grep -i i
I
사용자의 로캘에서 일치하지 않을 수 있습니다. 예를 들어 일부 터키어 로케일에서는 대문자 i
가 있고 İ
(점 참고) 소문자 I
가 ı
없습니다 (누락 된 점 참고).
¹ 텍스트 인코딩에 따라 반드시 옳은 것은 아닙니다. UTF-8 또는 1 바이트 문자 세트 (예 : iso-8859-1)에 유효하지만 반드시 UTF-8이 아닌 멀티 바이트 문자 세트는 아닙니다.
예를 들어, zh_HK.big5hkscs
로케일 (홍콩, BIG5 한자 인코딩의 홍콩 변형을 사용하는)에 있고 해당 문자 세트로 인코딩 된 파일에서 영어 문자를 찾으려면 다음 중 하나를 수행하십시오.
LC_ALL=C grep '[[:alpha:]]'
또는
LC_ALL=C grep '[a-zA-Z]'
그 문자 세트 (및 다른 많은 문자이지만 UTF-8이 나온 이후 거의 사용되지 않기 때문에)에는 많은 문자 에 A-Za-z 문자의 ASCII 인코딩에 해당하는 바이트가 포함되어 있기 때문에 잘못되었습니다 . 예를 들어, 모든 A䨝䰲丕乙乜你再劀劈呸哻唥唧噀噦嚳坽
(및 그 이상)에는의 인코딩이 포함되어 있습니다 A
. ASCII에서와 같이 䨝
0x96 0x41 A
이며 0x41입니다. 따라서 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의 동작 은 기술적으로 지정되지 않습니다 . 실제로 대부분의 프로그램은이를 불투명 한 데이터로 취급하고 설명 된대로 전달합니다. 그러나 전부는 아닙니다. 특히 C
로켈 에서 실행되는 경우 Ruby는 바이트가 127보다 큰 char 데이터를 질식시킬 수 있습니다 . 나는 그것이 기술적으로 "적합한"것인지 솔직히 모르겠지만, 우리는 그것을 야생에서 보았습니다 .
perl
S '는 \x{7FFFFFFFFFFFFFFF}
유니 코드 코드 포인트 범위가 임의로 U + 10FFFF 제한되었지만) 및 (UTF-16 디자인 제한으로 인해) 일부 도구는 여전히 6 바이트 문자를 인식 / 생성합니다. 이것이 6 바이트 문자의 의미입니다. 유닉스 의미론에서, 하나의 문자는 하나의 코드 포인트입니다. 귀하의 하나 개 이상의 코드 포인트 "문자는" 더 일반적으로 문자에서 명확하게하기 위해 graphem 클러스터로 참조됩니다.
C
기본 로케일이고 "POSIX"는 "C"의 별명입니다. "C"는 ANSI-C에서 파생 된 것 같습니다. 아마도 ANSI-C는 "POSIX"로케일을 정의 할 것입니다.
C
케이트 이름이 "ANSI C"에서 파생 되었음을 의미하지는 않습니다 .
내가 알 수있는 한, OS X은 UTF-8 로켈에서 코드 포인트 조합 순서를 사용하므로 Stéphane Chazelas의 답변에 언급 된 일부 포인트는 예외입니다.
이것은 OS X에서 26을, Ubuntu에서 310을 인쇄합니다.
export LC_ALL=en_US.UTF-8
printf %b $(printf '\\U%08x\\n' $(seq $((0x11)) $((0x10ffff))))|grep -a '[a-z]'|wc -l
아래 코드는 OS X에서 아무것도 인쇄하지 않아 입력이 정렬되었음을 나타냅니다. 제거 된 6 개의 대리 문자는 잘못된 바이트 시퀀스 오류를 발생시킵니다.
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
(위의 예제 는 zsh에서 오류가 발생 하기 %b
때문에 사용 printf \\U25
합니다.)
GNU 시스템에서 데이터 정렬 순서가 동일한 일부 문자 및 문자 시퀀스는 OS X에서 동일한 데이터 정렬 순서를 갖지 않습니다. 이것은 OS X에서 첫 번째 (OS X sort
또는 GNU 사용 sort
)로 인쇄되지만 ② 우분투에서 첫 번째로 인쇄됩니다.
export LC_ALL=en_US.UTF-8;printf %s\\n ② ①|sort
이것은 OS X에서 세 줄 (OS X sort
또는 GNU 사용 sort
)을 인쇄하지만 우분투에서 한 줄을 인쇄합니다.
export LC_ALL=en_US.UTF-8;printf %b\\n \\u0d4c \\u0d57 \\u0d46\\u0d57|sort -u
xclock
warning (Missing charsets in String to FontSet conversion
) 으로 문제를 해결LC_ALL=C.UTF-8
하려면 키릴 문제를 피하기 위해 사용 하는 것이 좋습니다 . 이 환경 변수를 설정하려면~/.bashrc
파일 끝에 다음 줄을 추가해야 합니다. –export LC_ALL=C.UTF-8