ทำอย่างไรถึงจะได้ผลลัพธ์ที่ไม่เหมือนใครโดยไม่ต้องเรียงลำดับข้อมูล?


40
$ cat data.txt 
aaaaaa
aaaaaa
cccccc
aaaaaa
aaaaaa
bbbbbb
$ cat data.txt | uniq
aaaaaa
cccccc
aaaaaa
bbbbbb
$ cat data.txt | sort | uniq
aaaaaa
bbbbbb
cccccc
$

ผลที่ผมต้องการก็คือการแสดงทุกบรรทัดจากไฟล์ต้นฉบับลบที่ซ้ำกันทั้งหมด (ไม่เพียง แต่คนที่ติดต่อกัน) ขณะที่ยังคงคำสั่งเดิมของงบในแฟ้ม

ในตัวอย่างนี้ผลลัพธ์ที่ฉันกำลังมองหาคือ

aaaaaa
cccccc
bbbbbb

ฉันจะใช้uniqงานการดำเนินการทั่วไปได้อย่างไร?

คำตอบ:


54
perl -ne 'print unless $seen{$_}++' data.txt

หรือถ้าคุณต้องใช้ประโยชน์cat :

cat data.txt | perl -ne 'print unless $seen{$_}++'

นี่คือการawkแปลสำหรับระบบที่ไม่มี Perl:

awk '!seen[$0]++' data.txt
cat data.txt | awk '!seen[$0]++'

3
สคริปต์ awk ที่สั้นกว่าเล็กน้อยคือ{ if (!seen[$0]++) print }
ชั่วโมง

1
@fred ยกเว้นไฟล์ของคุณมีขนาดใหญ่มากทั้งสองเวอร์ชันใช้เวลาในการพิมพ์นานกว่าที่จะเรียกใช้
cjm

8
รุ่น awk สามารถทำแม้สั้นโดยออกออกif, printวงเล็บและวงเล็บ:awk '!seen[$0]++'
กอร์ดอน Davisson

2
@Legate เป็นชื่อของอาร์เรย์ที่เราบันทึกทุกบรรทัดที่เราเห็น คุณสามารถเปลี่ยนเป็น'!LarryWall[$0]++'awk ห่วงใย แต่ "เห็น" ช่วยให้ผู้คนเข้าใจโปรแกรมดีขึ้น
cjm

1
@Sadi ที่ควรถูกถามเป็นคำถามไม่ใช่ความคิดเห็น แต่บางบรรทัดในไฟล์นั้นลงท้ายด้วยช่องว่างและบางบรรทัดไม่ คำสั่งเหล่านี้พิจารณาทั้งบรรทัดอย่างมีนัยสำคัญรวมถึงช่องว่างที่ส่วนท้าย
cjm

13

johnมีเครื่องมือที่เรียกว่าunique:

usr@srv % cat data.txt | unique out
usr@srv % cat out
aaaaaa
cccccc
bbbbbb

เพื่อให้บรรลุเดียวกันโดยไม่ต้องใช้เครื่องมือเพิ่มเติมใน commandline เดียวมีความซับซ้อนมากขึ้น:

usr@srv % cat data.txt | nl | sort -k 2 | uniq -f 1 | sort -n | sed 's/\s*[0-9]\+\s\+//'
aaaaaa
cccccc
bbbbbb

nlพิมพ์หมายเลขบรรทัดที่ด้านหน้าของบรรทัดดังนั้นหากเราsort/ uniqข้างหลังพวกเขาเราสามารถเรียกคืนลำดับเดิมของบรรทัดได้ sedเพียงลบหมายเลขบรรทัดหลังจากนั้น;)


มีการรวมกันของคำสั่ง linux ทั่วไปที่สามารถทำสิ่งเดียวกันได้หรือไม่
Lazer

7
สิ่งที่คุณพลาดใน "โดยไม่ต้องเรียงลำดับข้อมูล"?
Totor

@Totor - ดูการตอบกลับของmenkusเพื่อแสดงความคิดเห็นที่คล้ายกัน @binfalse - วิธีที่สองของคุณใช้งานไม่ได้ (อาจใช้ได้กับตัวอย่างเล็ก ๆ น้อย ๆ แต่ไม่สามารถใช้งานได้กับอินพุตจริง) โปรดแก้ไขเช่นนี้ควรใช้งานได้:nl -ba -nrz data.txt | sort -k2 -u | sort | cut -f2
don_crissti

6

ฉันชอบที่จะใช้สิ่งนี้:

cat -n data.txt | sort --key=2.1 -b -u | sort -n | cut -c8-

cat -n เพิ่มหมายเลขบรรทัด

sort --key=2.1 -b -u เรียงลำดับในฟิลด์ที่สอง (หลังจากหมายเลขบรรทัดที่เพิ่ม) ละเว้นช่องว่างนำหน้ารักษาบรรทัดที่ไม่ซ้ำกัน

sort -n เรียงลำดับตามตัวเลขที่เข้มงวด

cut -c8- เก็บอักขระทั้งหมดจากคอลัมน์ 8 ถึง EOL (เช่นไม่ต้องใส่หมายเลขบรรทัดที่เรารวมไว้)


5
> ทำอย่างไรถึงจะได้ผลลัพธ์ที่ไม่เหมือนใครโดยไม่ต้องเรียงลำดับข้อมูล? > โดยไม่ต้องเรียงลำดับข้อมูล
Jan Wikholm

7
'ไม่ต้องเรียงลำดับข้อมูล' ปรากฏในชื่อเรื่องเท่านั้น ความต้องการที่แท้จริงคือ: "แสดงทุกบรรทัดจากไฟล์ต้นฉบับลบรายการที่ซ้ำกันทั้งหมด (ไม่ใช่เฉพาะรายการที่ต่อเนื่องกัน) ในขณะที่ยังคงคำสั่งดั้งเดิมของคำสั่งในไฟล์"
เมนู

1
@menkus สำคัญคือ "ในขณะที่ยังคงคำสั่งเดิมของคำสั่งในไฟล์" คำตอบนี้ไม่ประสบความสำเร็จ
Andrew Ferrier

2

Perl uniqมีโมดูลที่คุณสามารถใช้ที่มีฟังก์ชั่นที่เรียกว่า ดังนั้นถ้าคุณใส่ข้อมูลลงในอาเรย์ของ Perl คุณก็สามารถเรียกฟังก์ชั่นเช่นนี้เพื่อทำให้มันไม่เหมือนใคร แต่ยังคงรักษาลำดับเดิมเอาไว้

use List::MoreUtils qw(uniq)    
@output = uniq(@output);

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับโมดูลนี้ได้ที่นี่: รายการ :: MoreUtils


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