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


10

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

나는 그것이 버그라고 생각할 것이지만, 두 가지 다른 프로그램 (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
#

참고하시기 바랍니다 .. 그것은 아주 명확하게합니다. sort혼자합니다 (없이 -u ... 옵션) .. 간다 무엇, 나오는 문자를 중얼하지 않습니다 ... 그러나, 예상 할 수 있으므로 질에 갖는 "이국적인"유니 코드 문자의 설명 같은 정규 값을 ,이 정렬되지 않은 FIFO 그룹으로 정렬 된 출력의 "맨 위"에 출력되는 것 이외의 문자는 정렬되지 않습니다. 따라서 여기에는 실제로 두 가지 문제가 있습니다. 1. "순진하게 정렬 될 수없는 문자 모두의 독특한 "기능"예상, 및 2 " sortuniq(경우에 따라)을 잃게 데이터입니다.
Peter.O

업데이트 : Gilles가 언급 한대로 (로케일 별 정렬이 필수가 아니고 문자 순서가 적합 할 때) 다음 sort -uuniq함께 작동합니다. LC_COLLATE=C; echo -e "〼\n〇\n〇" |sort -u(또는 |uniq)
Peter.O

답변:


11

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

더 긴 버전 : 두 문자열을 비교하는 기본 함수는 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 로캘 컴파일러에 버그가 있는지 모르겠습니다.


@Gilles : 유익하고 자세한 설명을 주셔서 감사합니다. 이제 이해가 되겠지만, "안전하게" 정렬을 사용하는 방법에 대해 궁금 합니다. 특히 "로케일 구분"정렬을 따르지 않기 때문에 정렬 할 것입니다 ... 이것에 대한 빠른 해결 방법이 있습니까? ... 나는 점점이의 요령을 얻을 것이다, 그러나 '하룻밤'일어나지 않을 것입니다 ... 예 .. 내 는 / usr / share / 국제화 / / UTF-8 charmaps 문제의 문자 모두에 대한 참조를 포함 , 그러나이 UTF-8 정의 (?)에있는 것이 도움이되지 않는 것 같습니다 ... 오, 작은 신비가 없으면 인생은 어떨까요? :) ...
Peter.O

1
@fred charmaps/UTF-8는 데이터 정렬에 대해 아무 말도하지 않습니다 locales/en_US. 그것이 중요합니다. 첫 번째 규칙은 LC_COLLATE사용하지 않는 것 LC_COLLATE입니다. C (= POSIX) 로캘에서 데이터 정렬은 합리적입니다 (숫자 값을 기준으로 엄격).
Gilles 'SO- 악 그만해라'

2
분류고유의 앞에 경우가 가로 세로 잘 작동 LC_COLLATE=C... 감사합니다 ...
Peter.O

1
그것은이지 않는다 정렬이 유틸리티에서 작동하지 않습니다 하지만 glibc는 로케일이 잘못 설계되어있다. 이 동작은 POSIX에서 허용 하지만 (현재는 austingroupbugs.net/view.php?id=1070 참조 ) 불행하지만 바람직하지 않습니다.
Stéphane Chazelas

6

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

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

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


@til : 에 대해 알려 주셔서 감사합니다 msort. 선택적인 GUI를 통해 소개 내용을보다 쉽게 ​​이해할 수 있습니다. 생성 된 명령을 복사 할 수 있으면 매우 편리합니다 ... 그리고 유니 코드 문자를 정렬 하지만 ( 그러나 "buts"를 좋아하지는 않습니다 :) ...하지만 고유 한 옵션 이 없습니다 : (... 당신이 게시 한 링크에 언급 된대로 : Capabilities of GNU sort and BSD sort lacking in msort are the ability to merge files without sorting them (the --merge option) and the ability to emit only the first of an equal run (the --unique option)... 정렬은 작동하지만 :)
Peter.O
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.