ทุกที่ที่ฉันเห็นคนที่ต้องการเรียงลำดับรายการที่ไม่ซ้ำใครพวกเขาจะไปถึงsort | uniqเสมอ ฉันไม่เคยเห็นตัวอย่างที่มีคนใช้sort -uแทน ทำไมจะไม่ล่ะ? ความแตกต่างคืออะไรและทำไมการใช้ uniq จึงดีกว่าการจัดเรียงค่าสถานะเฉพาะ
ทุกที่ที่ฉันเห็นคนที่ต้องการเรียงลำดับรายการที่ไม่ซ้ำใครพวกเขาจะไปถึงsort | uniqเสมอ ฉันไม่เคยเห็นตัวอย่างที่มีคนใช้sort -uแทน ทำไมจะไม่ล่ะ? ความแตกต่างคืออะไรและทำไมการใช้ uniq จึงดีกว่าการจัดเรียงค่าสถานะเฉพาะ
คำตอบ:
sort | uniqมีอยู่ก่อนsort -uและเข้ากันได้กับช่วงกว้างของระบบแม้ว่าระบบที่ทันสมัยเกือบทั้งหมดรองรับ-u- มันเป็น POSIX มันเป็นส่วนใหญ่ย้อนกลับไปวันเมื่อsort -uไม่ได้อยู่ (และคนที่ไม่ได้มีแนวโน้มที่จะเปลี่ยนวิธีการของพวกเขาหากวิธีการที่พวกเขารู้ว่ายังคงทำงานเพียงมองifconfigเทียบกับipการนำไปใช้)
ทั้งสองมีแนวโน้มที่จะรวมกันเนื่องจากการลบรายการที่ซ้ำกันในไฟล์ต้องมีการเรียงลำดับ (อย่างน้อยในกรณีมาตรฐาน) และเป็นกรณีที่ใช้กันทั่วไปอย่างมากในการเรียง นอกจากนี้ยังเร็วขึ้นภายในเนื่องจากความสามารถในการดำเนินการทั้งสองในเวลาเดียวกัน (และเนื่องจากความจริงที่ว่ามันไม่ต้องการ IPC ระหว่างuniqและsort) โดยเฉพาะอย่างยิ่งหากไฟล์มีขนาดใหญ่sort -uมีแนวโน้มว่าจะใช้ไฟล์ระดับกลางน้อยลงเพื่อจัดเรียงข้อมูล
ในระบบของฉันฉันได้รับผลลัพธ์เช่นนี้อย่างสม่ำเสมอ:
$ dd if=/dev/urandom of=/dev/shm/file bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 8.95208 s, 11.7 MB/s
$ time sort -u /dev/shm/file >/dev/null
real 0m0.500s
user 0m0.767s
sys 0m0.167s
$ time sort /dev/shm/file | uniq >/dev/null
real 0m0.772s
user 0m1.137s
sys 0m0.273s
นอกจากนี้ยังไม่หน้ากากรหัสการกลับมาของsortซึ่งอาจจะมีความสำคัญ (ในเปลือกหอยที่ทันสมัยมีวิธีที่จะได้รับนี้เช่นbash's $PIPESTATUSอาร์เรย์ แต่เรื่องนี้ไม่เป็นความจริงเสมอ)
sort | uniqเพราะ 9 ครั้งจาก 10 ฉันไปป์ไลน์จริงuniq -cๆ
sort -uเป็นส่วนหนึ่งของ UNIX รุ่นที่ 7 ประมาณปี 1979 รุ่นที่sortไม่มีการสนับสนุน-uเป็นสิ่งที่ล้าสมัยอย่างแท้จริง - หรือเขียนขึ้นโดยไม่สนใจมาตรฐาน de พฤตินัยก่อนมาตรฐานทางกฎหมายของ POSIX ดูเพิ่มเติม Stack Overflow Sort & uniq ใน Linux shellจากปี 2010
ipเพราะ มันเป็นปี 2016 และโพสต์นี้ในปี 2013 แต่ฉันเพิ่งรู้เกี่ยวกับipคำสั่งตอนนี้
uniq -c" (และอาจจะเพิ่มอีกครั้งเพื่อsort -nr | head) ฉันสงสัยว่าอะไรเป็นสิ่งที่เทียบเท่ากับsort | uniqในกลุ่มเมื่อฉันพบว่ากลุ่มมี:sort uคำสั่ง และ TIL ก็sort -uมีอยู่เช่นกัน
sort -n | uniq sort -n -uยกตัวอย่างเช่นการต่อท้ายและช่องว่างนำหน้าจะถูกมองว่าเป็นสิ่งที่ซ้ำกันsort -n -uแต่ไม่ใช่ในอดีต! echo -e 'test \n test' | sort -n -uผลตอบแทนtestแต่echo -e 'test \n test' | sort -n | uniqกลับทั้งสองบรรทัด
ข้อแตกต่างประการหนึ่งคือuniqมีตัวเลือกเพิ่มเติมที่มีประโยชน์มากมายเช่นการข้ามเขตข้อมูลสำหรับการเปรียบเทียบและการนับจำนวนการทำซ้ำของค่า sortการ-uตั้งค่าสถานะใช้การทำงานของuniqคำสั่งที่ไม่มีการตกแต่งเท่านั้น
sort -uไม่สามารถส่งผ่านไปuniqยังเพื่อใช้ตัวเลือกที่เป็นประโยชน์บางอย่างของหลังเช่นการข้ามเขตข้อมูลสำหรับการเปรียบเทียบและนับจำนวนการทำซ้ำ"
ด้วยตาม POSIX sortและuniqs (GNU uniqปัจจุบันไม่สอดคล้องในเรื่องนั้น) มีความแตกต่างในการที่sortจะใช้ขั้นตอนวิธีการเรียงที่เกิดเหตุของการเปรียบเทียบสตริง (โดยปกติจะใช้strcoll()เพื่อเปรียบเทียบสตริง) ในขณะที่uniqการตรวจสอบตัวตนไบต์มูลค่า (โดยปกติจะใช้strcmp()) .
เรื่องนี้มีเหตุผลอย่างน้อยสองประการ
ในบางแห่งโดยเฉพาะอย่างยิ่งในระบบ GNU มีอักขระต่าง ๆ เรียงกัน ตัวอย่างเช่นในโลแคล en_US.UTF-8 บนระบบ GNU อักขระ①②③④⑤⑥⑦⑧⑨⑩ ... ทั้งหมดและอื่น ๆ อีกมากมายเรียงลำดับเดียวกันเพราะลำดับการเรียงลำดับไม่ได้ถูกกำหนดไว้ ตัวเลขอารบิก 0123456789 นั้นเรียงลำดับเหมือนกับเลขอารบิคอาหรับตะวันออก (Arabic )
สำหรับsort -u, orts เหมือนกับ as และ 0123 เหมือนกับ ٠١٢٣ ดังนั้นsort -uจะเก็บไว้เพียงอันเดียวในขณะที่สำหรับuniq(ไม่ใช่ GNU uniqที่ใช้strcoll()(ยกเว้นด้วย-i)), ①แตกต่างจาก②และ 0123 แตกต่างจาก ٠١٢٣ ดังนั้นuniqจะพิจารณาทั้งหมด 4 ที่ไม่ซ้ำกัน
strcollสามารถเปรียบเทียบสตริงของอักขระที่ถูกต้องเท่านั้น (พฤติกรรมไม่ได้กำหนดตาม POSIX เมื่ออินพุตมีลำดับของไบต์ที่ไม่ได้สร้างอักขระที่ถูกต้อง) ในขณะที่strcmp()ไม่สนใจอักขระเนื่องจากการเปรียบเทียบแบบไบต์ต่อไบต์เท่านั้น นั่นคือเหตุผลอื่นว่าทำไมsort -uอาจไม่ให้ทุกบรรทัดที่ไม่ซ้ำกันหากบางอันไม่เป็นข้อความที่ถูกต้อง sort|uniqในขณะที่ยังไม่ได้ระบุในการป้อนข้อความที่ไม่ใช่ข้อความในทางปฏิบัติมีแนวโน้มที่จะให้คุณบรรทัดที่ไม่ซ้ำกันด้วยเหตุผลนั้นข้างรายละเอียดปลีกย่อยเหล่านั้นสิ่งหนึ่งที่ยังไม่ได้รับการบันทึกไว้เพื่อให้ห่างไกลคือuniqเปรียบเทียบสายทั้ง lexically ขณะที่sort's -uเปรียบเทียบตามข้อกำหนดการจัดเรียงที่กำหนดในบรรทัดคำสั่ง
$ printf '%s\n' 'a b' 'a c' | sort -uk 1,1
a b
$ printf '%s\n' 'a b' 'a c' | sort -k 1,1 | uniq
a b
a c
$ printf '%s\n' 0 -0 +0 00 '' | sort -n | uniq
0
-0
+0
00
$ printf '%s\n' 0 -0 +0 00 '' | sort -nu
0
ฉันชอบที่จะใช้sort | uniqเพราะเมื่อฉันพยายามที่จะใช้-uตัวเลือก (กำจัดรายการที่ซ้ำกัน) เพื่อลบรายการที่ซ้ำกันที่เกี่ยวข้องกับสตริงตัวพิมพ์เล็กมันไม่ง่ายที่จะเข้าใจผลลัพธ์
หมายเหตุ: ก่อนที่คุณจะสามารถเรียกใช้ตัวอย่างด้านล่างนี้คุณจะต้องจำลองลำดับการเรียงมาตรฐาน C โดยทำดังต่อไปนี้:
LC_ALL=C
export LC_ALL
ตัวอย่างเช่นถ้าฉันต้องการเรียงลำดับไฟล์และลบรายการที่ซ้ำกันในขณะที่ในเวลาเดียวกันการรักษากรณีที่แตกต่างกันของสตริงที่แตกต่างกัน
$ cat short #file to sort
Pear
Pear
apple
pear
Apple
$ sort short #normal sort (in normal C collating sequence)
Apple #the lower case words are at the end
Pear
Pear
apple
pear
$ sort -f short #correctly sorts ignoring the C collating order
Apple #but duplicates are still there
apple
Pear
Pear
pear
$ sort -fu short #By adding the -u option to remove duplicates it is
apple #difficult to ascertain the logic that sort uses to remove
Pear #duplicates(i.e., why did it remove pear instead of Pear?)
ความสับสนนี้แก้ไขได้โดยไม่ใช้-uตัวเลือกในการลบข้อมูลที่ซ้ำกัน การใช้uniqสามารถคาดการณ์ได้มากขึ้น ด้านล่างแรกเรียงลำดับและละเว้นกรณีและจากนั้นส่งผ่านไปuniqยังเพื่อลบรายการที่ซ้ำกัน
$ sort -f short | uniq
Apple
apple
Pear
pear
-uตัวเลือกของการsortส่งออกครั้งแรกของการทำงานเท่ากัน (ดูหน้าคน) ดังนั้นจะsort -fuเกิดขึ้นครั้งแรกของทุกกรณีที่ไม่สำคัญ ตรรกะที่sortใช้เพื่อลบรายการที่ซ้ำกันสามารถคาดการณ์ได้
ความแตกต่างอีกอย่างที่ฉันพบในวันนี้คือเมื่อเรียงลำดับตามขอบเขตที่sort -uใช้ค่าสถานะเฉพาะกับคอลัมน์ที่คุณเรียงลำดับด้วย
$ cat input.csv
3,World,1
1,Hello,1
2,Hello,1
$ cat input.csv | sort -t',' -k2 -u
1,Hello,1
3,World,1
$ cat input.csv | sort -t',' -k2 | uniq
1,Hello,1
2,Hello,1
3,World,1