คำสั่งที่จะพิมพ์ค่าเพียงครั้งเดียวแม้ว่ามันจะปรากฏขึ้นหลายครั้ง


8

ฉันมีไฟล์ txt ขนาดใหญ่ซึ่งมีค่าซ้ำหลายครั้ง มีคำสั่งที่ฉันสามารถใช้ที่จะผ่านไฟล์และหากค่าหนึ่งปรากฏครั้งเดียวไม่ทำซ้ำอีกครั้ง?

SO4
HOH
CL
BME
HOH
SO4
HOH
CL
BME
HOH
SO4
HOH
SO4
HOH
CL
BME
HOH
SO4
HOH
CL
BME
HOH
CL

ดังนั้นควรมีลักษณะดังนี้:

S04   
HOH  
CL   
BME 

สิ่งนี้คือฉันมีค่าแตกต่างกันจำนวนมากดังนั้นฉันไม่สามารถทำมันเองแบบนี้ได้

คำตอบ:


11

คุณสามารถใช้คำสั่งsortกับตัวเลือก--unique:

sort -u input-file

หากคุณต้องการเขียนผลลัพธ์ไปที่ FILE แทนเอาต์พุตมาตรฐานให้ใช้ตัวเลือก--output=FILE:

sort -u input-file -o output-file

คำสั่งuniqยังสามารถนำไปใช้ ในกรณีนี้บรรทัดที่เหมือนกันต้องเป็นผลลัพธ์ดังนั้นข้อมูลจะต้องเรียงลำดับเบื้องต้น - ขอบคุณ@RonJohnสำหรับบันทึกนี้ :

sort input-file | uniq > output-file

ฉันชอบsortคำสั่งสำหรับกรณีที่คล้ายกันเพราะความเรียบง่าย แต่ถ้าคุณทำงานกับอาร์เรย์ขนาดใหญ่awkแนวทางจากคำตอบของ John1024 อาจมีประสิทธิภาพมากกว่า นี่คือการเปรียบเทียบเวลาระหว่างวิธีการที่กล่าวถึงซึ่งใช้กับไฟล์ (ตามตัวอย่างด้านบน) ที่มีเกือบ 5 ล้านบรรทัด:

$ cat input-file | wc -l
20000000

$ TIMEFORMAT=%R
$ time sort -u input-file | wc -l
64
7.495

$ time sort input-file | uniq | wc -l
64
7.703

$ time awk '!a[$0]++' input-file | wc -l      # from John1024's answer
64
1.271

$ time datamash rmdup 1 < input-file | wc -l  # from αғsнιη's answer
64
0.770

ความแตกต่างที่สำคัญอื่น ๆ คือที่@Ruslanกล่าวถึง:

sort -uจะพิมพ์ผลลัพธ์เมื่ออินพุตสิ้นสุดลงในขณะที่awkคำสั่งนี้จะพิมพ์แต่ละบรรทัดผลลัพธ์ใหม่ทันที (สิ่งนี้อาจสำคัญกว่าสำหรับอินพุต pip กว่าไฟล์)

นี่คือภาพประกอบ:

ป้อนคำอธิบายรูปภาพที่นี่

ในตัวอย่างด้านบนการวนซ้ำ (แสดงด้านล่าง) สร้างการผสมแบบสุ่ม 500 ชุดแต่ละชุดมีความยาวอักขระสามตัวของ AD ตัวอักษร รวมกันเหล่านี้จะประปาหรือawksort

for i in {1..500}; do cat /dev/urandom | tr -dc A-D | head -c 3; echo; done

1
มันเป็นคำสั่งที่ง่ายมาก! ขอบคุณมาก! ทั้งหมดที่ดีที่สุด
djordje

2
โอ้สำหรับวันที่ยูทิลิตี้เดียวทำสิ่งหนึ่งและทำได้ดี !! sort input-file | uniq!!!!
RonJohn

15

หากคุณต้องการคงบรรทัดเอาท์พุทตามลำดับเช่นเดียวกับบรรทัดอินพุตให้ใช้:

$ awk '!a[$0]++' file
SO4
HOH
CL
BME

มันทำงานอย่างไร:

สิ่งนี้ใช้อาร์เรย์ที่เชื่อมโยงaเพื่อนับจำนวนครั้งที่เห็นแต่ละบรรทัดก่อนหน้านี้ หากไม่เคยเห็นมาก่อนหน้านี้สายจะถูกพิมพ์


2
มันยุ่งยากมากawkแต่sort -uเป็นวิธีที่ง่าย
Pierre François

4
@ PierreFrançois แต่sort -uก็เป็นวิธีที่ช้าที่สุด :) ฉันได้อัปเดตคำตอบของฉันพร้อมการเปรียบเทียบเวลาระหว่างสองแนวทาง
pa4080

4
นอกจากนี้sort -uจะพิมพ์ผลลัพธ์เฉพาะเมื่ออินพุตสิ้นสุดลงในขณะที่awkคำสั่งนี้จะพิมพ์บรรทัดผลลัพธ์ใหม่แต่ละบรรทัดทันที (สิ่งนี้อาจสำคัญกว่าสำหรับอินพุต pip กว่าไฟล์)
Ruslan

ขอบคุณสำหรับบันทึกนี้ @Ruslan! ฉันพยายามอธิบายมันในคำตอบของฉัน
pa4080

ฉันต้องสารภาพว่าวิธีการแก้ปัญหาเป็นหนึ่งที่ดีมากแม้จะไม่ได้เป็นเรื่องง่ายที่จะอ่านเป็นawk sort
Pierre François

1

คุณสามารถใช้GNU ได้ datamashที่นี่เช่นกันและจะเก็บคำสั่งซื้อไว้

datamash rmdup 1 < infile

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