uniq ไม่แตกต่างกันมากพอที่จะมี uniq --unique อย่างไร


35

นี่คือคำสั่งในไฟล์สุ่มจากpastebin :

wget -qO - http://pastebin.com/0cSPs9LR | wc -l
350
wget -qO - http://pastebin.com/0cSPs9LR | sort -u | wc -l
287
wget -qO - http://pastebin.com/0cSPs9LR | sort | uniq | wc -l
287
wget -qO - http://pastebin.com/0cSPs9LR | sort | uniq -u | wc -l
258

หน้าคนไม่ชัดเจนในสิ่งที่-uธงทำ คำแนะนำใด ๆ?


4
ลองจัดเรียง | uniq -d | wc -l และคุณอาจเห็นความแตกต่าง :)
58

คำตอบ:


42

เวอร์ชั่นสั้น:

  • uniqไม่มี-uทำให้ทุกบรรทัดของเอาต์พุตไม่ซ้ำกัน
  • uniq -uเพียงพิมพ์ทุกสายที่ไม่ซ้ำกันจากการป้อนข้อมูล

รุ่นที่ยาวกว่าเล็กน้อย:

uniqใช้สำหรับจัดการกับไฟล์ที่มีการทำซ้ำบรรทัดและเฉพาะเมื่อบรรทัดเหล่านั้นปรากฏอย่างต่อเนื่องในอินพุต ดังนั้นเพื่อจุดประสงค์บรรทัดที่ไม่ซ้ำกันคือสิ่งที่ไม่ซ้ำกันทันที

( uniqมีหน่วยความจำระยะสั้นที่ จำกัด อย่างมาก; มันจะไม่มีทางจำได้ว่าจะมีบรรทัดปรากฏขึ้นก่อนหน้านี้ในอินพุตหรือไม่เว้นแต่จะเป็นบรรทัดก่อนหน้าทันที - นี่คือเหตุผลuniqที่มักจะจับคู่กับsort)

เมื่อพบการทำงานของเส้นที่ซ้ำกัน, uniqโดยไม่ต้อง-uหาเรื่อง, พิมพ์หนึ่งสำเนาของบรรทัดนั้น (มันทำให้ทุกบรรทัดของเอาต์พุตไม่ซ้ำกัน )

ด้วย-uอาร์กิวเมนต์มันพิมพ์สำเนาศูนย์ของบรรทัดนั้น - การทำงานของรายการที่ซ้ำกันเพิ่งถูกตัดออกจากเอาต์พุต


1
ฉันหวังว่าจะมีตัวเลือกที่ไม่จำเป็นต้องเรียงลำดับ แต่มันจะต้องเก็บไฟล์ทั้งหมดในหน่วยความจำ (หรือทำบัญชีจำนวนมากที่มีแฮชและออฟเซ็ตหากแหล่งที่มาเป็นไฟล์ปกติ)
Random832

3
@ Random832: และมันจะต้องตัดสินใจว่าคู่หูคนไหนที่จะต้องเก็บไว้ (ก่อนอื่นสิ่งอื่นกำหนด) และการตัดสินใจนั้นจะส่งผลกระทบต่ออัลกอริทึมทั่วโลก การทะเลาะ
Steve Jessop

1
@ Random832: ถ้ามันเป็นเพียงเกี่ยวกับจำนวนตัวอักษรในการพิมพ์คุณสามารถใช้แทนsort -u sort | uniq
โอลิเวอร์

@oliver ในบางครั้งฉันต้องการความสามารถในการเก็บอินสแตนซ์แรกของบรรทัดใด ๆ โดยไม่ต้องจัดเรียงใหม่และเขียนสคริปต์ให้ทำ
Random832

1
@hvd: หากเวอร์ชันของคุณuniqทำการปรับมาตรฐานและการจัดเรียงใช่ แต่ถึงกระนั้นก็เป็นเพียงการพิจารณาในท้องถิ่น - คุณรู้ว่าในบรรทัดที่เรียงลำดับผลลัพธ์จะปรากฏขึ้นและเพียงแค่ต้องเลือกว่าจะให้บรรทัดใดติดกันหลายบรรทัด หากอินพุตไม่ได้ถูกจัดเรียงการตัดสินใจจะมีผลต่อการดำเนินการทั้งหมดของการไม่รวมตัวอย่างเช่นหากคุณจะเก็บสำเนาที่ซ้ำกันครั้งสุดท้ายคุณจะไม่สามารถส่งออกสิ่งใดจนกว่าคุณจะอ่านบรรทัดสุดท้ายของอินพุต ...
Steve Jessop

53

uniqด้วยการ-uข้ามบรรทัดที่มีการซ้ำซ้อน ดังนั้น:

$ printf "%s\n" 1 1 2 3 | uniq
1
2
3
$ printf "%s\n" 1 1 2 3 | uniq -u
2
3

โดยปกติแล้วuniqพิมพ์บรรทัดได้สูงสุดหนึ่งครั้ง (สมมติว่าอินพุตเรียงลำดับ) ตัวเลือกนี้จะพิมพ์บรรทัดที่มีลักษณะเฉพาะอย่างแท้จริง(ไม่ปรากฏขึ้นอีกครั้ง)


11
นั่นคือuniqสามารถเรียกใช้ได้distinctเนื่องจากมันพิมพ์บรรทัดที่ต่างกันทั้งหมดในขณะที่uniq -uพิมพ์บรรทัดที่ไม่ซ้ำกันทั้งหมด
Steve Jessop

มันไม่ได้มีเอกลักษณ์อย่างแท้จริงuniqในGNU ในบางพื้นที่
cuonglm

ฉันจะต้องมีการอ่านคำตอบที่ได้รับการยอมรับหลายครั้ง แต่มันก็ไม่ได้จมอยู่ในตัวอย่างและวรรคของคุณหลังจากที่มันทำให้มันชัดเจนมาก (และจะกลับมาอีกครั้งอ่านคำตอบที่ได้รับการยอมรับฉันได้รับที่มากเกินไป) :).
Madivad

18

ข้อมูลจำเพาะ uniq POSIXอธิบายไว้อย่างชัดเจน:

-u
    Suppress the writing of lines that are repeated in the input.

-uตัวเลือกทำให้uniqไม่พิมพ์บรรทัดซ้ำ

uniqการใช้งานส่วนใหญ่ใช้การเปรียบเทียบไบต์ในขณะที่ GNU uniqใช้ลำดับการเรียงเพื่อกรองบรรทัดที่ซ้ำกัน ดังนั้นจึงสามารถสร้างผลลัพธ์ที่ไม่ถูกต้องในบางภาษาเช่นในen_US.UTF-8ภาษา:

$ printf '%b\n' '\U2460' '\U2461' | uniq
①

และ-uทำให้คุณไม่มีสาย:

$ printf '%b\n' '\U2460' '\U2461' | uniq -u
<blank>

ดังนั้นคุณควรกำหนดสถานที่Cเพื่อรับการเปรียบเทียบไบต์:

$ printf '%b\n' '\U2460' '\U2461' | LC_ALL=C uniq
①
②

3
โปรดทราบว่าสิ่งที่ผิดที่นี่ไม่มากuniq(แต่เห็นได้ชัดว่าเจตนาของ POSIX คือควรทำการเปรียบเทียบแบบไบต์แทน strcoll () การเปรียบเทียบในsort -u) เป็นโลแคลที่มีการเรียง①เหมือนกับ as อย่างน้อย GNU มีความสอดคล้องกับuniq sort -u
Stéphane Chazelas

@ StéphaneChazelas - ในสเป็คที่ทำให้ชัดเจน?
mikeserv

เกี่ยวกับuniqจำเป็นต้องทำ memcmp / strcmp เมื่อเทียบกับ strcoll ที่ไม่ชัดเจนมากกับผม แต่ที่กำลังจะเจฟฟ์ เกี่ยวกับที่ตั้งของ GNU ที่มี①การเรียงลำดับเหมือนกับ②นั่นเป็นข้อผิดพลาดอย่างชัดเจนเนื่องจากไม่มีเหตุผลว่าทำไมพวกเขาจึงควรเรียงลำดับเดียวกัน ที่อนุญาตโดย POSIX แต่มีการเปลี่ยนแปลงบางอย่างเกิดขึ้น
Stéphane Chazelas

8

ปกติ:

echo "a b a b c c c" | tr ' ' '\n'
a
b
a
b
c
c
c

uniq: ไม่มีสองบรรทัดที่ซ้ำกันตามมา

echo "a b a b c c c" | tr ' ' '\n' | uniq
a
b
a
b
c

เรียงลำดับ

echo "a b a b c c c" | tr ' ' '\n' | sort
a
a
b
b
c
c
c

sort -u: ไม่มีสองบรรทัดที่ซ้ำกัน

echo "a b a b c c c" | tr ' ' '\n' | sort -u
a
b
c

sort / uniq: ชัดเจนทั้งหมด

echo "a b a b c c c" | tr ' ' '\n' | sort | uniq
a
b
c

นับเหตุการณ์ที่แตกต่าง

echo "a b a b c c c" | tr ' ' '\n' | sort | uniq -c
2 a
2 b
3 c

เฉพาะบรรทัดที่ไม่ซ้ำกัน (ไม่เรียงก่อน)

echo "a b a b c c c" | tr ' ' '\n' | uniq -u
a
b
a
b

เฉพาะบรรทัดที่ไม่ซ้ำกัน (หลังจากเรียงลำดับ)

echo "a b a b c c c Z" | tr ' ' '\n' | sort | uniq -u
Z

uniq -d: พิมพ์เฉพาะบรรทัดที่ซ้ำกันหนึ่งรายการสำหรับแต่ละกลุ่ม

echo "a b a b c c c" | tr ' ' '\n' | uniq -d
c

.. นับแล้ว

echo "a b a b c c c" | tr ' ' '\n' | uniq -dc
3 c

ตัวอย่างที่ชัดเจนดี :)
Madivad
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.