왜 정렬은 ɛ = e라고 말합니까?


25

ɛ( "라틴 엡실론")은 일반적으로 영어 "침대"로 모음 소리를 나타 내기 위해 특정 아프리카 언어에서 사용되는 문자입니다. 유니 코드에서는 U + 025B로 인코딩되어 일상과 매우 다릅니다 e.

그러나 sort다음과 같은 경우 :

eb
ed
ɛa
ɛc

sort고려 ɛ하고 e동등한 것으로 보입니다 .

ɛa
eb
ɛc
ed

무슨 일이야? 그리고 목적을 위해 구별 ɛ하고 e구별 할 수있는 방법이 sort있습니까?


21
정렬 규칙은 당신의 인터넷 검색 도움이된다면, '정렬'이라고
대니 Pflughoeft - BlueRaja

1
텍스트 파일 안에 특정 수의 ea믹싱 을 넣고 ɛa정렬하십시오. 항상 ea전에 정렬됨을 알 수 ɛa있습니다. 따라서 그들은 평등하다고 간주되지 않습니다.
Bakuriu

명백한 요점 일 수도 있지만, 아직 명시 적으로 제안하지는 않았습니다. $ (certain_african_language)로 단어를 정렬하는 경우 자연스럽게 할 일은 로케일을 $ (certain_african_language)로 설정하는 것입니다.
Federico Poloni

@FedericoPoloni 아주 좋은 지적입니다! 불행히도 나는이 언어로 만들어진 로케일을 찾을 수 없었습니다.
Draconis

1
@ GermánBouzas 이것은 특히 라틴 알파벳과 어울리도록 디자인 된 "라틴 엡실론"입니다. 그들은 거의 동일하게 보이지만 라틴 엡실론은 U + 025B이며 그리스 엡실론은 U + 03B5입니다.
Draconis

답변:


67

아니요, 그것들은 동등한 것으로 간주되지 않으며 동일한 기본 가중치를 갖습니다. 따라서 첫 번째 근사에서는 동일한 정렬입니다.

GNU 시스템 (여기서는 glibc 2.27)에서 / usr / share / i18n / locales / iso14651_t1_common (대부분의 로케일의 기준으로 사용됨)을 보면 다음과 같이 표시됩니다.

<U0065> <e>;<BAS>;<MIN>;IGNORE # 259 e
<U025B> <e>;<PCL>;<MIN>;IGNORE # 287 ɛ
<U0045> <e>;<BAS>;<CAP>;IGNORE # 577 E

e, ɛE동일한 기본 중량을 가질 eE같은 보조 무게 만 번째 중량 그들을 구별.

문자열을 비교할 때 sort( strcoll()표준 libc 함수는 문자열을 비교하는 데 사용) 모든 문자의 기본 가중치를 비교하는 것으로 시작하고 문자열이 기본 가중치와 같은 경우에만 두 번째 가중치로 이동합니다 (다른 가중치와 마찬가지로). .

첫 번째 근사에서 정렬 순서에서 대소 문자가 무시되는 것처럼 보입니다. Ab사이의 종류 aaac하지만 Ab종류 전이나 후에 할 수 있습니다 ab(일부 언어가 가지고있는 언어 규칙에 따라 <MIN><CAP>영국 영어, 일부처럼 <CAP>전에 <MIN>에스토니아어처럼).

경우 e같은 정렬 순서를 같이했다 ɛ, printf '%s\n' e ɛ | sort -u단 하나의 행을 반환합니다. 그러나 같은 <BAS>종류의 이전 <PCL>, e혼자 종류의 ɛ . eɛe이후에 정렬 EEE하더라도 (2 차 가중치에서) EEE정렬 eee합니다 (이 경우 3 번째 가중치까지 올라갑니다).

이제 glibc 2.27을 사용하는 시스템에서 다음을 실행합니다.

sed -n 's/\(.*;[^[:blank:]]*\).*/\1/p' /usr/share/i18n/locales/iso14651_t1_common |
  sort -k2 | uniq -Df1

정확히 4 개의 가중치로 정의 된 문자가 꽤 있음을 알 수 있습니다. 특히, ɛ의 가중치는 다음과 같습니다.

<U01DD> <e>;<PCL>;<MIN>;IGNORE
<U0259> <e>;<PCL>;<MIN>;IGNORE
<U025B> <e>;<PCL>;<MIN>;IGNORE

그리고 충분히 :

$ printf '%s\n' $'\u01DD' $'\u0259' $'\u025B' | sort -u
ǝ
$ expr ɛ = ǝ
1

이것은 GNU libc 로켈의 버그로 볼 수 있습니다. 대부분의 다른 시스템에서 로케일은 다른 모든 문자가 결국 다른 정렬 순서를 갖도록합니다. 정렬 순서가 같은 정렬 끝나지 않는 수천 개의 문자가 있기 때문에 GNU 로케일에, 그것은 깨는처럼 (모든 종류의 문제를 일으키는, 심지어 악화 comm, join, ls비 결정적 주문을 갖거나 globs와 ... 따라서 이러한 문제를 해결하기 위해 사용LC_ALL=C 하는 것이 좋습니다 .

@ninjalj가 코멘트에서 언급했듯이, 2018 년 8 월에 릴리스 된 glibc 2.28은 AFAICS를 통해 그 부분에서 약간 개선되었지만 여전히 동일한 정렬 순서로 정의 된 일부 문자 또는 조합 요소가 있습니다. glibc 2.28이 설치된 Ubuntu 18.10 및 en_GB.UTF-8 로켈에서.

$ expr $'L\ub7' = $'L\u387'
1

(U? 00B7이 L/ l?! 와 결합 된 경우에만 U + 0387과 동등한 것으로 간주되는 이유 ).

과:

$ perl -lC -e 'for($i=0; $i<0x110000; $i++) {$i = 0xe000 if $i == 0xd800; print chr($i)}' | sort > all-chars-sorted
$ uniq -d all-chars-sorted | wc -l
4
$ uniq -D all-chars-sorted | wc -l
1061355

(정렬 순서가 정의되지 않은 다른 문자와 동일하게 백만 자 이상의 문자 (유니 코드 범위의 95 %, 2.27에서 98 %로 줄임)).

참조 :


3
이것이 바로 내가 찾던 것입니다! 완전성을 <PCL>위해 무엇을 의미합니까? 다른 사람들은 Capital, Miniscule, Basic 인 것 같습니다.
Draconis

3
@Draconis, collating-symbol <PCL> # 16 particulier / 특별
Stéphane Chazelas

실제로 우리 가 파일에 무리를 ea넣고 ɛa섞으면 우리 sort는 모든 것을 eas 앞에 정렬하는 것을 볼 수 ɛa있습니다.
Bakuriu

2
glibc는 2.28에서 코드 포인트는 4 레벨의 무게에 대한 대체 표기를 참조 sourceware.org/git/... sourceware.org/bugzilla/show_bug.cgi?id=14095
ninjalj

1
@cat, 죄송합니다 strcoll(). 편집을 참조하십시오.
Stéphane Chazelas

15

남자 정렬 :

   ***  WARNING  ***  The locale specified by the environment affects sort
   order.  Set LC_ALL=C to get the traditional sort order that uses native
   byte values.

따라서 다음을 시도하십시오. LC_ALL=C sort file.txt


1
작동합니다! 그러나 기본 로케일이 왜 완전히 분리 된 코드 포인트를 동일한 것으로 간주합니까? 왜 이런 일이 발생하는지 궁금합니다.
Draconis

@Draconis "기본 로케일"이란 무엇입니까?
Kamil Maciorowski

@KamilMaciorowski 환경 변수의 빈 값. 어떤 로캘에 해당하는지 잘 모르겠습니다.
Draconis

3
@Draconis LC_ALL가 비어 있으면 sort다른 LC_*변수 LANG또는 일부 구성 파일을 사용할 수 있습니다 .
NieDzejkob

1
LC_COLLATE문자열 정렬 별 LANG이며, 일반적인 것입니다.
ShadowRanger

8

문자 ɛ는 e와 같지 않지만 일부 로케일은 데이터 정렬시이 기호를 서로 가깝게 모을 수 있습니다. 그 이유는 언어에 따라 다르지만 일부 역사적 또는 정치적 배경이기도합니다. 예를 들어 대부분의 사람들은 € uro 통화 가 사전 에 유럽 에 근접 할 것으로 예상합니다 .

어쨌든 현재 실행을 사용하는 데이터 정렬을 확인하려면 다음 locale의는 locale -a당신의 시스템의 변경 데이터 정렬 말에 사용 가능한 로케일의 목록을 제공합니다C 단지 하나의 정렬 실행 LC_COLLATE=C sort file. 마지막으로 다른 로케일이 파일을 정렬하는 방법을 확인하십시오.

for loc in $(locale -a)
    do echo ____"${loc}"____
    LC_COLLATE="$loc" sort file
done

그렙 도구에 결과를 파이프하여 필요에 맞는 로케일을 선택하십시오.


이것은 훌륭한 설명이지만 기호는 서로 가깝지 않고 동일한 것으로 간주됩니다.
Draconis

1
아니요, 동일하지 않은 것으로 간주됩니다. ea파일에 평범한 줄을 추가 하면 출력 과 결과를 sort -u모두 얻을 수 있습니다 . 가장 좋은 전략 대 대조는 피하는 것입니다 ( ). 그렇지 않으면, 많은 추악한 일들이 일어날 것입니다 (예. 에 일치 하고 있지만 ). eaɛaexport LC_COLLATE=C/tmp/[a-z]bash/tmp/a/tmp/A/tmp/Z
mosvy

@mosvy Huh, 흥미로운… 그래서 주문 목적은 동일하지만 고유성 목적은 아닌 것으로 간주됩니까?
Draconis

그들은 같은 것으로 간주되지 않습니다. 여기에 대한 설명을 참조 하십시오 .
mosvy

1
@ninjalj는 glibc fnmatch()및 regexp 범위 에서 고정 될 수 있지만 bash그 자체로는 범위를 구현 하지는 않습니다 strcoll(). ksh93은 범위 구현이 사용 strcoll()되며 범위 끝의 경우를 확인하고 양쪽 끝이 모두 소문자 인 경우에만 소문자로만 일치 하므로 문제가 없었습니다 . zsh 범위는 strcoll ()이 아닌 코드 포인트를 기반으로 수행되므로 문제가 없습니다.
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.