Trường hợp dòng `uniq` hoặc` sort -u` của tôi biến mất ở đâu, với một số ký tự unicode


10

Điều gì đang xảy ra trong đoạn mã sau đây? Tôi không nhận được đầu ra mong đợi của tôi.

Tôi nghĩ đó là một lỗi, nhưng nó xảy ra với 2 chương trình khác nhau (uniq và sort), vì vậy tôi nghi ngờ đó là một cái gì đó để làm với ... tốt, tôi không biết những gì .. vì vậy câu hỏi.

3 (4) ví dụ đầu tiên hoạt động, nhưng lần thứ 4 thất bại!.

Tôi mong đợi hành vi tương tự cho bất kỳ và tất cả các nhân vật.
I E. để in ra 2 dòng (từ 3 dòng đầu vào) ... nhưng trong trường hợp thứ 4, tôi chỉ nhận được 1 dòng (cho cả hai sort -uuniq); Hai cái giống hệt nhau biến mất!

Tôi đã chuyển đổi đầu ra '\ n' thành không gian để thu gọn tầm nhìn.

Tôi đang sử dụng uniqsắp xếp từ (GNU coreutils) 7.4 ... đang chạy trên máy tính để bàn Ubuntu 10.04.3 LTS.

Kịch bản:

{
  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
}

Đầu ra:

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
#

Xin lưu ý .. Để làm cho nó khá rõ ràng. sortmột mình (không có tùy chọn -u ) ... không ngấu nghiến các ký tự .. Những gì diễn ra, xuất hiện ... Tuy nhiên, như lời giải thích của Gilles về các ký tự unicode "kỳ lạ" có cùng giá trị chính tắc , những thứ này các ký tự không được sắp xếp, ngoài ra chúng là đầu ra dưới dạng nhóm FIFO chưa được sắp xếp thành "đầu" của đầu ra sắp xếp ... Vì vậy, có hai vấn đề thực sự ở đây: 1. Các ký tự không được sắp xếp một cách ngây thơ "Dự kiến ​​và 2. Tính năng" duy nhất "của cả hai sortuniqmất dữ liệu (trong một số trường hợp).
Peter.O

Cập nhật: Như được đề cập bởi Gilles (khi sắp xếp cụ thể theo địa phương là không cần thiết và thứ tự nhân vật phù hợp) sort -uuniqhoạt động tốt với: LC_COLLATE=C; echo -e "〼\n〇\n〇" |sort -u(hoặc |uniq)
Peter.O

Câu trả lời:


11

Phiên bản ngắn: collation không thực sự hoạt động trong các tiện ích dòng lệnh.

Phiên bản dài hơn: chức năng cơ bản để so sánh hai chuỗi là strcoll. Mô tả không hữu ích lắm, nhưng phương pháp hoạt động theo khái niệm là chuyển đổi cả hai chuỗi thành dạng chính tắc, sau đó so sánh hai dạng chính tắc. Hàm strxfrmxây dựng dạng chính tắc này.

Chúng ta hãy quan sát các dạng chính tắc của một vài chuỗi (với GNU libc, trong phần nén Debian):

$ 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

Như bạn có thể thấy, và có dạng chính tắc giống nhau. Tôi nghĩ đó là bởi vì những nhân vật này không được đề cập trong các bảng đối chiếu của en_US.UTF-8miền địa phương. Họ, tuy nhiên, hiện diện ở một địa phương Nhật Bản.

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

Mã nguồn cho dữ liệu miền địa phương (trong nén nén Debian) nằm trong /usr/share/i18n/locales/en_US, bao gồm /usr/share/i18n/locales/iso14651_t1_common. Tệp này không có mục cho U3007hoặc U303C, chúng cũng không được bao gồm trong bất kỳ phạm vi nào tôi có thể tìm thấy.

Tôi không quen thuộc với các quy tắc để xây dựng thứ tự đối chiếu , nhưng theo những gì tôi hiểu, cụm từ có liên quan là

Biểu tượng UNDEFINED sẽ được hiểu là bao gồm tất cả các giá trị bộ ký tự được mã hóa không được chỉ định rõ ràng hoặc thông qua biểu tượng dấu chấm lửng. .

Có vẻ như Glibc thay vào đó bỏ qua các ký tự không được chỉ định. Tôi không biết liệu có một lỗ hổng trong hiểu biết của tôi về thông số POSIX hay không, nếu tôi bỏ lỡ điều gì đó trong định nghĩa ngôn ngữ của Glibc, hoặc nếu có lỗi trong trình biên dịch miền địa phương Glibc.


@Gilles: Cám ơn những lời giải thích thông tin và chi tiết .. Nó làm cho một số cảm giác bây giờ, nhưng tôi lại tự hỏi, làm thế nào để "an toàn" sử dụng loại .. Tôi không sau khi một "nhạy cảm locale" đặc biệt sắp xếp, vì vậy bất kỳ thô sắp xếp sẽ làm ... Có một cách giải quyết nhanh chóng cho điều này? ... và tôi dần dần sẽ nhận được hang của điều này, nhưng nó sẽ không xảy ra 'qua đêm' ... ví dụ .. tôi / usr / share / i18n / charmaps / UTF-8 chứa tham chiếu đến cả những nhân vật trong câu hỏi , nhưng theo định nghĩa UTF-8 này (?) dường như không giúp được gì ... Ồ, cuộc sống sẽ ra sao nếu không có những bí ẩn nhỏ. :) ...
Peter.O

1
@fred charmaps/UTF-8không nói gì về đối chiếu, đó là locales/en_USvấn đề. Nguyên tắc đầu tiên LC_COLLATElà: không sử dụng LC_COLLATE. Trong ngôn ngữ C (= POSIX), đối chiếu là hợp lý (hoàn toàn dựa trên các giá trị ký tự số).
Gilles 'SO- đừng trở nên xấu xa'

2
Các sắp xếpđộc đáo làm việc tốt khía cạnh khi đứng trước LC_COLLATE=C... nhờ ...
Peter.O

1
Không phải sự đối chiếu đó không hoạt động trong các tiện ích mà là các địa điểm glibc được thiết kế kém. Hành vi đó là (hiện tại, nhưng xem austingroupbugs.net/view.php?id=1070 ) được POSIX cho phép, nhưng không may và không mong muốn.
Stéphane Chazelas

6

Để "an toàn" sortchuỗi Unicode, có thể xem qua msort:

[...] Msort cung cấp sự linh hoạt cao hơn trong việc chọn các trường khóa, nhiều loại so sánh hơn, khả năng sử dụng quy tắc đối chiếu từ các vị trí khác nhau trên các khóa khác nhau, khả năng xử lý số trong các hệ thống số không thuộc phương Tây và thiếu nhiều tùy chọn khác trong sắp xếp GNU và sắp xếp BSD. Trong khi msort hiểu Unicode, sắp xếp GNU và sắp xếp BSD thì không. [...]

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


@til: Cảm ơn đã cho tôi biết msort. GUI tùy chọn giúp giới thiệu dễ dàng hơn một chút để cảm nhận về những gì được cung cấp. Có thể sao chép lệnh được tạo rất tiện dụng ... Và vâng, nó sắp xếp các ký tự unicode, nhưng (bạn không chỉ thích những "buts" đó :) ... nhưng nó không có tùy chọn duy nhất : (... như đã đề cập trên liên kết bạn đã đăng: 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)... Cách sắp xếp hoạt động :)
Peter.O
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.