문맥

문맥
  • 문맥
  • 문제 발견
    • 질문 번호 1
    • 질문 번호 2
    • 질문 번호 3
  • 질문

문맥

오늘은 파일에서 한자가 포함된 유일한 줄을 유지하고 싶습니다. sort나는 이 유틸리티에 익숙하고 파일에서 중복 라인을 제거하는 것이 이 플래그를 사용하는 것만큼 쉽기 때문에 이 유틸리티를 사용하기로 결정했습니다 -u. sort한자를 올바르게 사용 하려면 로케일을 변경해야 한다는 것을 배웠습니다 . 나는 다른 로케일을 사용하여 sort다른 동작을 발견했습니다. 이 기사에서는 내가 찾은 결과를 제시합니다.

파일에서 중복된 줄을 제거하는 작업은 여러 도구/프로그래밍 언어를 사용하여 수행할 수 있다는 것을 알고 있습니다. 이 작업을 위한 도구를 제안한 모든 사람에게 감사하지만, 로캘에 대해 더 자세히 알아보고 이것이 Unix 유틸리티에 어떤 영향을 미치는지에 더 관심이 있습니다.

문제 발견

질문 번호 1

다음은 내 시스템의 로케일 설정입니다.

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

다음 이름을 고려하십시오.main.txt


내 .en_US.UTF-8$LANG줄번호를 잃어버렸어요. 2

sort -u main.txt

LANG설정을 통해 이 문제를 해결했습니다 zh_CN.UTF-8.

export LANG=zh_CN.UTF-8
sort -u main.txt

내가 만든다하나의 질문스택 오버플로에 대한 이 질문에 대해. 누군가 로케일을 바꾸자고 제안했는데 효과가 있는 것 같고 문제가 해결된 줄 알았는데 나중에 보니 문제가 아니더군요. 2 및 질문 번호. 3(아래 설명).

질문 번호 2

이제 파일에 두 줄을 추가한다고 가정해 보겠습니다.main.txt


답변1

sort -u출력은 로케일에서 동일하게(동일한 정렬 순서로) 대조되는 각 행 세트 중 하나입니다.

GNU 시스템(GNU libc를 사용하는 시스템)에서는 대부분의 로케일에서 많은 문자 1이 정의되지 않은 정렬 순서를 가지며, 이는 결국 동일하게 정렬된다는 의미이며, 동일한 정렬 순서를 갖도록 명시적으로 정의된 문자도 있습니다.

바이트를 텍스트로 디코딩할 수 없는 경우 일반적으로 무시되거나 동일한 정렬 순서²를 갖는 것으로 간주됩니다.

따라서 sort -u바이트 대 바이트 동등 비교를 기반으로 고유한 줄을 제공하려면 텍스트가 어떤 인코딩으로 작성되었는지에 관계없이 각 바이트를 문자로 디코딩할 수 있는 로캘과 전체 순서가 설정된 로캘이 필요합니다.

가장 간단한 방법은 C바이트 == 문자 맵이 있는 로케일을 사용하는 것입니다(특정 바이트는명확하지 않다문자), 정렬은 바이트 값(적어도 ASCII 기반 시스템에서는)을 기반으로 하며 특정 시스템에서 찾을 수 있는 유일한 로케일입니다.

귀하의 경우 더 나은 동작을 제공하는 이유를 이해하려면 일반적으로 GNU 시스템에서 찾을 수 있는 로케일 정의를 zh_CN살펴보세요 . 여기에서 다음을 찾을 수 있습니다./usr/share/i18n/localezh_CN

LC_COLLATE
copy "iso14651_t1_pinyin"
END LC_COLLATE

어디 iso14651_t1_pinyin:

copy "iso14651_t1_common"

en_US그런 다음 많은 추가 중국어 문자 의 정렬을 지정하고 iso14651_t1_common.

zh_CN.GB18030 또는 zh_CN.GBK로 설정 LC_CTYPE(전달 LANG)하고 UTF-8로 인코딩된 파일을 처리하려고 하면 sort일반적으로 UTF-8로 인코딩된 텍스트의 바이트가 인코딩되지 않기 때문에 해당 행을 텍스트로 디코딩할 수 없습니다. GB18030 인코딩으로 유효한 형식을 구성하면 문제가 더욱 악화됩니다.

여기에서 고유한(바이트 대 바이트 비교에 따라) 행을 얻으려는 동시에 해당 로케일에서 "올바르게" 정렬된 출력을 얻으려면 다음을 수행할 수 있습니다.

LC_ALL=C sort -u your-file | sort

첫 번째는 sort중복 항목을 제거하고 두 번째는 로케일 정렬 규칙에 따라 나머지 행을 정렬합니다.

LC_ALL대신 LANGor LC_CTYPE+를 사용하는 LC_COLLATE이유는 이 변수가 모든 것을 재정의하는 변수( which보다 우선 적용됨)이기 때문입니다 LC_ALL. LC_individual_setting따라서 LANGor가 환경에 다른 방식으로 설정된 경우에도 LANG여전히 LC_COLLATE작동합니다.

이론적으로는 다음과 같이 할 수도 있습니다.

LC_ALL= LC_CTYPE=C LC_COLLATE=C sort

"문자 유형" 및 "조합" 설정만 설정되고 다른 로케일 범주는 그대로 두고( LANG또는 로 재정의됨 LC_xxx) 사용된 나머지 범주는 예를 들어 오류 메시지 sort용입니다 . 설정한 경우 US만 사용됩니다. 어쨌든 영어 메시지는 ASCII 문자만 포함하기 때문에 올바르게 표시됩니다. 예를 들어:LC_MESSAGESLC_CTYPE=C

$ LC_MESSAGES=zh_CN LC_CTYPE=C sort --version
sort (GNU coreutils) 9.1
Copyright (C) 2022 Free Software Foundation, Inc.
??? GPLv3+:GNU ???????? 3 ?????? <https://gnu.org/licenses/gpl.html>?
????????:??????????????
?????????,????????

? Mike Haertel ? Paul Eggert ???

자세한 내용은 다음에서 확인할 수 있습니다.


엄밀히 말하면 기본 단위는 아니다.특징하지만요소 구성ch예를 들어 특정 체코 지역 사이 h또는 내부에서 여러 유사한 문자로 구성될 수 있습니다 .i

sort² GNU가 아닌 일부 구현 sort에서는 NUL 문자 또는 지나치게 긴 줄도 차단됩니다.

관련 정보