ทุกที่ที่ฉันเห็นคนที่ต้องการเรียงลำดับรายการที่ไม่ซ้ำใครพวกเขาจะไปถึง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
และuniq
s (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