บรรทัด `uniq 'ของฉันหรือ` sort -u' หายไปไหนด้วยอักขระ Unicode บางตัว


10

เกิดอะไรขึ้นในข้อมูลโค้ดต่อไปนี้ ฉันไม่ได้รับผลลัพธ์ที่คาดหวัง

ฉันคิดว่ามันเป็นข้อผิดพลาด แต่มันเกิดขึ้นสำหรับ 2 โปรแกรมที่แตกต่างกัน (uniq และ sort) ดังนั้นฉันสงสัยว่ามันเป็นบางสิ่งที่ต้องทำกับ ... อืมฉันไม่รู้ว่า ... ดังนั้นคำถาม

ตัวอย่าง 3 (4 จาก) แรกทำงานได้ แต่ 4 ล้มเหลว!

ฉันคาดว่าจะมีพฤติกรรมแบบเดียวกันสำหรับตัวละครทุกตัว
กล่าวคือ เพื่อพิมพ์ 2 บรรทัด (จากอินพุต 3 บรรทัด) ... แต่ในกรณีที่ 4 ฉันได้รับเพียง 1 บรรทัด (สำหรับทั้งคู่sort -uและuniq); สอง lins ที่เหมือนกันเพิ่งหายไป!

ฉันได้แปลงเอาท์พุท '\ n' เป็นพื้นที่เพื่อความกะทัดรัด

ฉันใช้uniqและเรียงลำดับจาก (GNU coreutils) 7.4 ... ทำงานบน Ubuntu 10.04.3 LTS desktop

สคริปต์:

{
  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 ) ... ไม่ได้ฮุบตัวอักษร .. อะไรจะเกิดขึ้นออกมา ... อย่างไรก็ตามอย่างที่คาดไว้โดยคำอธิบายของกิลส์ของ "แปลกใหม่" ตัวอักษร unicode ที่มีค่ามาตรฐานเดียวกันเหล่านี้ ตัวละครไม่ได้รับการจัดเรียงนอกเหนือจากที่พวกเขาจะถูกส่งออกเป็นกลุ่ม FIFO ไม่ได้เรียงลำดับไปยัง "ด้านบน" ของการจัดเรียงของเอาท์พุท ... ดังนั้นจึงมีสองประเด็นจริง ๆ ที่นี่: 1. ตัวละครที่ไม่ได้เรียงตามอาจ "คาดหวังและ 2 คุณลักษณะ" ที่ไม่ซ้ำกัน "ของทั้งสองsortและuniqข้อมูลสูญหาย (ในบางกรณี)
Peter.O

อัปเดต: ตามที่กล่าวถึงโดยGilles (เมื่อการเรียงลำดับโลแคลไม่จำเป็นและลำดับตัวอักษรเหมาะสม) sort -uและuniqทำงานได้ดีกับ: LC_COLLATE=C; echo -e "〼\n〇\n〇" |sort -u(หรือ|uniq)
Peter.O

คำตอบ:


11

เวอร์ชั่นย่อ: การเปรียบเทียบไม่ทำงานในยูทิลิตี้บรรทัดคำสั่ง

อีกรุ่น: strcollฟังก์ชั่นพื้นฐานเพื่อเปรียบเทียบสองสายคือ คำอธิบายไม่เป็นประโยชน์มาก แต่วิธีการดำเนินการเกี่ยวกับความคิดคือการแปลงทั้งสองสตริงเป็นรูปแบบบัญญัติและจากนั้นเปรียบเทียบทั้งสองรูปแบบบัญญัติ ฟังก์ชั่นstrxfrmสร้างรูปแบบบัญญัตินี้

ลองสังเกตรูปแบบบัญญัติของสตริงสองสามข้อ (ด้วย GNU libc ภายใต้ Debian squeeze):

$ 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

อย่างที่คุณเห็น〼และ〇มีรูปแบบมาตรฐานที่เหมือนกัน ฉันคิดว่าเป็นเพราะตัวละครเหล่านี้ไม่ได้กล่าวถึงในตารางเปรียบเทียบของen_US.UTF-8สถานที่ อย่างไรก็ตามพวกมันอยู่ในสถานที่ของญี่ปุ่น

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

ซอร์สโค้ดสำหรับข้อมูลโลแคล (ใน Debian squeeze) นั้น/usr/share/i18n/locales/en_USรวม/usr/share/i18n/locales/iso14651_t1_commonอยู่ด้วย ไฟล์นี้ไม่มีรายการU3007หรือหรือU303Cจะไม่รวมอยู่ในช่วงที่ฉันสามารถหาได้

ฉันไม่คุ้นเคยกับกฎในการสร้างคำสั่งเปรียบเทียบแต่จากสิ่งที่ฉันเข้าใจการใช้ถ้อยคำที่เกี่ยวข้องคือ

สัญลักษณ์ UNDEFINED จะถูกตีความว่าเป็นการรวมถึงค่าชุดอักขระที่เข้ารหัสทั้งหมดที่ไม่ได้ระบุอย่างชัดเจนหรือผ่านสัญลักษณ์รูปไข่ (…) หากไม่มีการระบุสัญลักษณ์ UNDEFINED และชุดอักขระที่เข้ารหัสปัจจุบันมีอักขระที่ไม่ได้ระบุไว้ในส่วนนี้ยูทิลิตี้จะออกข้อความเตือนและวางตัวอักษรดังกล่าวไว้ท้ายคำสั่งการจัดเรียงอักขระ

ดูเหมือนว่า Glibc จะไม่สนใจอักขระที่ไม่ได้ระบุแทน ฉันไม่ทราบว่ามีข้อบกพร่องของความเข้าใจเกี่ยวกับข้อมูลจำเพาะ POSIX ของฉันหรือไม่หากฉันพลาดบางสิ่งในการกำหนดสถานที่ของ Glibc หรือหากมีข้อผิดพลาดในคอมไพเลอร์ที่ตั้งของ Glibc


@Gilles:ขอบคุณสำหรับคำอธิบายที่ให้ข้อมูลและรายละเอียด .. มันทำให้รู้สึกบางอย่างตอนนี้ แต่ฉันสงสัยว่าวิธีการ "ใช้อย่างปลอดภัย" ใช้การจัดเรียง .. ฉันไม่ได้หลังจากการเรียงลำดับ "สถานที่ที่สำคัญ" โดยเฉพาะอย่างยิ่ง การจัดเรียงจะทำ ... มีวิธีแก้ปัญหาอย่างรวดเร็วสำหรับเรื่องนี้? ... และฉันจะค่อยๆได้รับสิ่งนี้ แต่จะไม่เกิดขึ้น 'ข้ามคืน' ... เช่น .. / usr / share / i18n / charmaps / UTF-8 ของฉันมีการอ้างอิงถึงตัวละครทั้งสองในคำถาม แต่การอยู่ในคำจำกัดความ UTF-8 นี้ (?) ดูเหมือนจะไม่ช่วย ... โอเคชีวิตจะเป็นอย่างไรถ้าปราศจากความลึกลับเล็ก ๆ น้อย ๆ :) ...
Peter.O

1
@ เฟรดcharmaps/UTF-8ไม่ได้พูดอะไรเกี่ยวกับการเปรียบเทียบมันเป็นlocales/en_USเรื่องสำคัญ กฎข้อแรกของคือไม่ได้ใช้LC_COLLATE LC_COLLATEในโลแคล C (= POSIX) การเปรียบเทียบนั้นสมเหตุสมผล (โดยยึดตามค่าอักขระตัวเลขอย่างเคร่งครัด)
Gilles 'หยุดความชั่วร้าย'

2
การเรียงลำดับและลักษณะที่ไม่ซ้ำกันทำงานได้ดีเมื่อนำหน้าด้วยLC_COLLATE=C... ขอบคุณ ...
Peter.O

1
ไม่ใช่การเปรียบเทียบไม่ทำงานในระบบสาธารณูปโภคแต่ตำแหน่งที่ตั้ง glibc นั้นได้รับการออกแบบมาไม่ดี พฤติกรรมดังกล่าวคือ (ในปัจจุบัน แต่เห็นaustingroupbugs.net/view.php?id=1070 ) ที่ POSIX อนุญาต แต่โชคร้ายและไม่พึงปรารถนา
Stéphane Chazelas

6

หากต้องการsortสตริง Unicode ที่"ปลอดภัย" อาจดูได้ที่msort:

[... ] Msort ช่วยเพิ่มความยืดหยุ่นในการเลือกเขตข้อมูลคีย์ชนิดการเปรียบเทียบเพิ่มเติมความสามารถในการใช้กฎการจัดเรียงจากตำแหน่งที่ตั้งต่าง ๆ บนคีย์ที่แตกต่างกันความสามารถในการจัดการหมายเลขในระบบตัวเลขที่ไม่ใช่ตะวันตกและตัวเลือกอื่น ๆ ใน GNU sort และ BSD sort ในขณะที่ msort เข้าใจ Unicode, GNU sort และ BSD sort ไม่ [ ... ]

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.