Tại sao sắp xếp nói rằng = e?


25

ɛ("Latin epsilon") là một chữ cái được sử dụng trong một số ngôn ngữ châu Phi, thường là để thể hiện âm nguyên âm trong tiếng Anh "bed". Trong Unicode, nó được mã hóa thành U + 025B, rất khác biệt so với hàng ngày e.

Tuy nhiên, nếu tôi sortnhư sau:

eb
ed
ɛa
ɛc

có vẻ như sortxem xét ɛetương đương:

ɛa
eb
ɛc
ed

Những gì đang xảy ra ở đây? Và có một cách để làm ɛekhác biệt cho sortmục đích ing?


21
quy tắc sắp xếp được gọi là 'đối chiếu', nếu điều đó giúp bạn googling của bạn
BlueRaja - Danny Pflughoeft

1
Cố gắng đặt một số lượng nhất định eatrộn lẫn ɛabên trong một tệp văn bản và sắp xếp nó. Bạn sẽ thấy rằng nó luôn luôn sắp xếp eatrước ɛa. Vì vậy, không có họ không được coi là bằng nhau.
Bakuriu

Có thể là một điểm rõ ràng, nhưng tôi chưa thấy nó gợi ý rõ ràng: nếu bạn đang sắp xếp các từ trong $ (nhất định_african_lingu), điều tự nhiên cần làm là đặt ngôn ngữ thành $ (nhất định_african_lingu).
Federico Poloni

@FedericoPoloni Một điểm rất tốt! Thật không may, tôi không thể tìm thấy bất kỳ ngôn ngữ nào được tạo ra cho ngôn ngữ này.
Draconis

1
@ GermánBouzas Đây là "Latin epsilon", một hình thức được thiết kế để phù hợp với bảng chữ cái Latin. Chúng trông khá giống nhau, nhưng epsilon Latin là U + 025B, trong khi epsilon của Hy Lạp là U + 03B5.
Draconis

Câu trả lời:


67

Không, nó không coi chúng là tương đương, chúng chỉ có cùng trọng lượng chính. Vì vậy, trong xấp xỉ đầu tiên, họ sắp xếp giống nhau.

Nếu bạn xem / usr / share / i18n / loc / iso14651_t1_common (làm cơ sở cho hầu hết các địa phương) trên hệ thống GNU (ở đây với glibc 2.27), bạn sẽ thấy:

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

e, ɛEcó trọng lượng sơ cấp như nhau, eEtrọng lượng thứ cấp tương tự, chỉ có trọng lượng thứ ba phân biệt chúng.

Khi so sánh các chuỗi, sort( strcoll()hàm libc tiêu chuẩn được sử dụng để so sánh các chuỗi) bắt đầu bằng cách so sánh các trọng số chính của tất cả các ký tự và chỉ đi theo trọng số thứ hai nếu các chuỗi bằng với các trọng số chính (v.v. với các trọng số khác) .

Đó là cách trường hợp dường như bị bỏ qua theo thứ tự sắp xếp trong xấp xỉ đầu tiên. Absắp xếp giữa aaac, nhưng Abcó thể sắp xếp trước hoặc sau abtùy thuộc vào quy tắc ngôn ngữ (một số ngôn ngữ có <MIN>trước <CAP>giống như trong tiếng Anh Anh, một số <CAP>trước <MIN>như ở tiếng Estonia).

Nếu ecó cùng thứ tự sắp xếp như ɛ, printf '%s\n' e ɛ | sort -usẽ chỉ trả về một dòng. Nhưng như <BAS>sắp xếp trước <PCL>, emột mình sắp xếp trước ɛ . eɛesắp xếp sau EEE(ở trọng lượng thứ cấp) mặc dù EEEsắp xếp sau eee(mà chúng ta cần tăng lên trọng lượng thứ ba).

Bây giờ nếu trên hệ thống của tôi với glibc 2.27, tôi chạy:

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

Bạn sẽ nhận thấy rằng có khá nhiều ký tự đã được xác định với cùng 4 trọng số. Cụ thể, của chúng tôi có cùng trọng số như:

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

Và chắc chắn:

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

Đó có thể được coi là một lỗi của GNU libc local. Trên hầu hết các hệ thống khác, các địa phương đảm bảo rằng tất cả các ký tự khác nhau có thứ tự sắp xếp khác nhau cuối cùng. Trên miền địa phương GNU, nó được thậm chí tệ hơn, như có hàng ngàn nhân vật mà không có một trật tự sắp xếp và kết thúc sắp xếp giống nhau, khiến cho tất cả các loại của các vấn đề (như phá vỡ comm, join, lshoặc những đống có đơn đặt hàng không xác định ... ), do đó khuyến nghị sử dụng LC_ALL=Cđể giải quyết những vấn đề đó .

Theo ghi nhận của @ninjalj trong các bình luận, glibc 2.28 được phát hành vào tháng 8 năm 2018 đi kèm với một số cải tiến trên mặt trận đó mặc dù AFAICS, vẫn còn một số ký tự hoặc các yếu tố đối chiếu được xác định theo thứ tự sắp xếp giống hệt nhau. Trên Ubuntu 18.10 với glibc 2.28 và trong miền địa phương en_GB.UTF-8.

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

(tại sao U + 00B7 chỉ được coi là tương đương với U + 0387 khi kết hợp với L/ l?!).

Và:

$ 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

(vẫn còn hơn 1 triệu ký tự (95% phạm vi Unicode, giảm từ 98% trong 2,27) sắp xếp giống như các ký tự khác khi thứ tự sắp xếp của chúng không được xác định).

Xem thêm:


3
Điều này thật đúng với gì mà tôi đã tìm kiếm! Để cho đầy đủ, những gì <PCL>đứng cho? Những người khác dường như là Thủ đô, rất nhỏ và cơ bản?
Draconis

3
@Draconis, ký hiệu đối chiếu <PCL> # 16 particulier / peculiar
Stéphane Chazelas

Thật vậy, nếu chúng ta đặt một bó eaɛatrộn lẫn với nhau trong một tệp, chúng ta sẽ thấy rằng sortsắp xếp tất cả eas trước ɛas.
Bakuriu

2
Từ glibc 2.28, codepoint nên được sử dụng làm dự phòng cho trọng lượng cấp 4, xem sourceware.org/git/iêu sourceware.org/ormszilla/show_bug.cgi?id=14095
ninjalj 27/10/18

1
@cat, xin lỗi, ý tôi là strcoll(), xem chỉnh sửa.
Stéphane Chazelas

15

người đàn ông sắp xếp:

   ***  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.

Vì vậy, hãy thử: LC_ALL=C sort file.txt


1
Đó là công việc! Nhưng tại sao miền địa phương mặc định coi các điểm mã hoàn toàn riêng biệt này giống nhau? Tôi tò mò tại sao điều này xảy ra.
Draconis

@Draconis "miền địa phương mặc định" là gì?
Kamil Maciorowski

@KamilMaciorowski Một giá trị trống của biến môi trường; Tôi không chắc miền địa phương tương ứng với cái gì.
Draconis

3
@Draconis nếu LC_ALLtrống, sortcó thể sử dụng các LC_*biến khác LANGhoặc một số tệp cấu hình.
NieDzejkob

1
LC_COLLATElà một chuỗi cụ thể sắp xếp theo chuỗi, LANGlà một tổng quát.
ShadowRanger

8

Ký tự không bằng e, nhưng một số địa phương có thể tập hợp các dấu hiệu này gần nhau khi đối chiếu. Lý do cho điều này là ngôn ngữ cụ thể, nhưng cũng có một số nền tảng lịch sử hoặc thậm chí chính trị. Ví dụ, hầu hết mọi người có thể mong đợi rằng tiền € uro đến gần với châu Âu trong từ điển.

Dù sao để xem đối chiếu nào bạn đang sử dụng chạy locale, locale -asẽ cung cấp cho bạn danh sách các địa điểm có sẵn trên hệ thống và để thay đổi đối chiếu Cchỉ với một lần chạy sắp xếp LC_COLLATE=C sort file. Cuối cùng để xem các địa phương khác nhau có thể sắp xếp tệp của bạn thử như thế nào

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

Đưa kết quả vào một số công cụ greping để chọn miền phù hợp với nhu cầu của bạn.


Đây là một lời giải thích tuyệt vời, nhưng các biểu tượng dường như được coi là giống hệt nhau, không chỉ gần nhau.
Draconis

1
Không, chúng không được coi là giống hệt nhau. Thêm một eadòng đơn giản vào tệp, sau đó với sort -ubạn sẽ nhận được cả hai eaɛatrong đầu ra. Chiến lược tốt nhất so với đối chiếu là tránh ( export LC_COLLATE=C). Nếu không, nhiều điều xấu xí sẽ xảy ra (ví dụ. /tmp/[a-z]Trong bashsẽ phù hợp /tmp/a/tmp/Anhưng không phải /tmp/Z).
mosvy

@mosvy Huh, thú vị vì vậy chúng được coi là giống nhau cho mục đích đặt hàng nhưng không phải cho mục đích duy nhất?
Draconis

chúng không được coi là giống nhau. xem ở đây một lời giải thích về nó.
mosvy

1
@ninjalj, điều đó có thể được cố định trong fnmatch()phạm vi glibc và regrec, nhưng không phải trong một số trường hợp tự bashthực hiện phạm vi của nó bằng cách sử dụng strcoll(). ksh93 không bao giờ gặp sự cố vì việc sử dụng phạm vi của nó sử dụng strcoll()và cũng kiểm tra trường hợp kết thúc phạm vi và chỉ khớp với các ký tự chữ thường nếu cả hai đầu đều là chữ thường. phạm vi zsh không có vấn đề vì nó được thực hiện dựa trên điểm mã, không phải strcoll ().
Stéphane Chazelas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.