[unix] 유니 코드 문자와 함께 내`uniq` 또는`sort -u` 줄이 사라진 곳

다음 코드 스 니펫에서 무슨 일이 일어나고 있습니까? 예상 출력을 얻지 못했습니다.

나는 그것이 버그라고 생각할 것이지만, 두 가지 다른 프로그램 (uniq 및 sort)에 대해 발생하므로, 그것이 관련이 있다고 생각합니다 … 글쎄, 나는 무엇을 모른다.

처음 3 개 중 4 개 예제는 작동하지만 4 번째는 실패합니다!.

모든 캐릭터에 대해 동일한 동작을 기대합니다.
즉. (입력의 3 개 라인에서) 2 개 라인을 인쇄 …하지만 4 번째 경우에, 난 단지 (모두 1 개 라인 얻을 sort -uuniq); 두 개의 동일한 린이 사라집니다!

컴팩트하게보기 위해 출력 ‘\ n’을 공간으로 변환했습니다.

내가 사용하고 UNIQ종류 (GNU의로 coreutils)에서 7.4 … 우분투 10.04.3 LTS 데스크탑에서 실행합니다.

스크립트 :

{
  locale -k LC_COLLATE
  echo
  for c1 in x 〼 ;do
    for c2 in z 〇 ;do
      echo -n "asis   : "; echo -e "$c1\n$c2\n$c2"          |tr '\n' ' ';echo
      echo -n "uniq   : "; echo -e "$c1\n$c2\n$c2" |uniq    |tr '\n' ' ';echo
      echo -n "sort -u: "; echo -e "$c1\n$c2\n$c2" |sort -u |tr '\n' ' ';echo
      echo
    done
    echo
  done
}

출력 :

collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=2081
collate-codeset="UTF-8"

asis   : x z z
uniq   : x z
sort -u: x z

asis   : x 〇 〇
uniq   : x 〇
sort -u: 〇 x


asis   : 〼 z z
uniq   : 〼 z
sort -u: 〼 z

asis   : 〼 〇 〇
uniq   : 〼
sort -u: 〼

# In the last example (of 4) where did the '〇' go? .. U+3007 IDEOGRAPHIC NUMBER ZERO
#



답변

짧은 버전 : 데이터 정렬은 실제로 명령 행 유틸리티에서 작동하지 않습니다.

더 긴 버전 : 두 문자열을 비교하는 기본 함수는 strcoll입니다. 설명은별로 도움이되지 않지만 개념적 조작 방법은 두 문자열을 표준 형식으로 변환 한 다음 두 표준 형식을 비교하는 것입니다. 함수는 strxfrm이 정식 형식을 구성합니다.

몇 가지 문자열의 정식 형태를 관찰 해 봅시다 (데비안 스퀴즈 아래 GNU libc 사용).

$ export LC_ALL=en_US.UTF-8
$ perl -C255 -MPOSIX -le 'print "$_ ", unpack("h*", strxfrm($_)) foreach @ARGV' b a A à 〼 〇
b d010801020
a c010801020
A c010801090
à 101010102c6b
〼 101010102c6b102c6b102c6b
〇 101010102c6b102c6b102c6b

보시다시피, 〼와 the의 정식 형식은 같습니다. en_US.UTF-8로케일 의 데이터 정렬 테이블에 이러한 문자가 언급되어 있지 않기 때문이라고 생각합니다 . 그러나 일본어 로케일로 제공됩니다.

$ export LC_ALL=ja_JP.UTF-8
$ perl -C255 -MPOSIX -le 'print "$_ ", unpack("h*", strxfrm($_)) foreach @ARGV' 〼 〇
〼 303030
〇 3c9b

로케일 데이터 (데비안 스퀴즈)의 소스 코드는에 /usr/share/i18n/locales/en_US포함되어 /usr/share/i18n/locales/iso14651_t1_common있습니다. 이 파일에 U3007또는에 대한 항목이 없거나 U303C찾을 수있는 범위에 포함되어 있지 않습니다.

데이터 정렬 순서를 작성 하는 규칙에 익숙하지 않지만 이해 한 바에 따르면 관련 문구는

UNDEFINED 기호는 명시 적으로 또는 생략 기호를 통해 지정되지 않은 모든 코드화 된 문자 세트 값을 포함하는 것으로 해석됩니다. (…) UNDEFINED 기호가 지정되지 않고 현재 코딩 된 문자 세트에이 섹션에 지정되지 않은 문자가 포함 된 경우, 유틸리티는 경고 메시지를 발행하여 문자 조합 순서의 끝에 문자를 배치해야합니다.

Glibc가 지정되지 않은 문자를 무시하는 것처럼 보입니다. POSIX 사양에 대한 이해에 결함이 있는지, Glibc의 로캘 정의에서 뭔가를 놓쳤거나 Glibc 로캘 컴파일러에 버그가 있는지 모르겠습니다.


답변

sort유니 코드 문자열 을 “안전하게”하려면 다음을 살펴보십시오 msort.

[…] Msort는 키 필드 선택, 더 많은 비교 유형, 다른 키의 다른 로케일에서 조합 규칙을 사용하는 기능, 비 서구 번호 시스템에서 숫자를 처리하는 기능 및 기타 다양한 옵션이없는 유연성을 제공합니다. GNU 정렬 및 BSD 정렬에서. msort는 유니 코드를 이해하는 반면 GNU 정렬과 BSD 정렬은 그렇지 않습니다. […]

http://www.billposer.org/Software/msort.html


답변