การพิมพ์ลายเส้นที่เป็นเอกลักษณ์


15

มีวิธีแก้ปัญหาที่ดีกว่าสำหรับการพิมพ์บรรทัดที่ไม่ซ้ำกันนอกเหนือจากการรวมกันของsortและuniq?


1
คุณหมายถึงอะไร "ดีกว่า"?
เกบ

@gabe ไม่ต้องการให้ไฟล์ทั้งหมดถูกเก็บไว้ในหน่วยความจำ
Let_Me_Be

sort(เช่น coreutils ของ GNU) บางรุ่นใช้ไฟล์ชั่วคราวและการรวมภายนอกถ้าอินพุตมีขนาดใหญ่เกินไปที่จะพอดีกับ RAM และรุ่นอื่น ๆ ส่วนใหญ่มี-mตัวเลือกดังนั้นสิ่งนี้สามารถทำได้อย่างชัดเจนโดยการป้อนข้อมูล (เช่นกับsplit), การเรียงลำดับแต่ละอันแล้วรวมชิ้นส่วน
jhnc

คำตอบ:


25

หากต้องการพิมพ์แต่ละบรรทัดที่เหมือนกันจะมีเพียงหนึ่งบรรทัดเท่านั้น

sort -u

หากต้องการพิมพ์เฉพาะบรรทัดที่ไม่ซ้ำกันในลำดับใด ๆ :

sort | uniq -u

หากต้องการพิมพ์แต่ละบรรทัดที่เหมือนกันเพียงครั้งเดียวตามลำดับการปรากฏครั้งแรก: (สำหรับแต่ละบรรทัดให้พิมพ์บรรทัดหากยังไม่เห็นจากนั้นในกรณีใด ๆ ก็จะเพิ่มตัวนับที่เห็น)

awk '!seen[$0] {print}
     {++seen[$0]}'

หากต้องการพิมพ์เฉพาะบรรทัดที่ไม่ซ้ำกันตามลำดับการปรากฏครั้งแรกของพวกเขา: (บันทึกแต่ละบรรทัดในseenและlinesถ้าเกิดขึ้นเป็นครั้งแรกในตอนท้ายของอินพุตให้พิมพ์บรรทัดตามลำดับที่ปรากฏ แต่เฉพาะที่เห็นเท่านั้น ครั้งเดียว)

awk '!seen[$0]++ {lines[i++]=$0}
     END {for (i in lines) if (seen[lines[i]]==1) print lines[i]}'

8
แล้วไงawk '!seen[$0]++ {print}'ล่ะ
asoundmove

10
หรือสั้นกว่าawk '!seen[$0]++'นั้นเนื่องจาก{print}คำสั่งนั้นมีคำสั่งว่าง
quazgar

3

บางรุ่น (ส่วนใหญ่?) sortมีการ-uตั้งค่าสถานะที่ทำหน้าที่uniqโดยตรง อาจจะมีบางข้อ จำกัด ความยาวสายขึ้นอยู่กับการดำเนินการว่า sort|uniqแต่คุณมีผู้ที่อยู่กับธรรมดา


1
เอ่อ? sort -uกลับไปที่ V7 เป็นอย่างน้อย
geekosaur

Hum ... ฉันคิดว่าฉันจำ Solaris หรือ AIX ไม่ได้ ฉันผิดทั้งคู่มีมัน
Mat

Solaris และ AIX มี-uแต่ยังมีข้อจำกัดความยาวบรรทัด 512 ตัว (อันที่จริงฉันคิดว่าอยู่ที่ไหนสักแห่งใน Solaris 9 Sun เพิ่มขึ้นเป็น 5120 แต่ GNU ยังคงชนะอยู่)
geekosaur

@geekosaur: คุณแน่ใจเหรอ? งานที่ทำเพื่อลบขีด จำกัด 512 ไบต์บนความยาวบรรทัดในการเรียงลำดับถูกบันทึกไว้ใน 'ทฤษฎีและการปฏิบัติในการสร้างเส้นทางการเรียงลำดับการทำงาน' โดย JP Linderman, Bell System Technical วารสาร, 63, 1827-1843 (1984)
Jonathan Leffler

0

Perl ทำงานให้คุณหรือไม่? สามารถเก็บบรรทัดในลำดับเดิมแม้ว่ารายการที่ซ้ำกันจะไม่ติดกัน awkนอกจากนี้คุณยังสามารถรหัสมันในหลามหรือ

while (<>) {
    print if $lines{$_}++ == 0;
}

ซึ่งสามารถย่อให้เหลือเพียง

perl -ne 'print unless $lines{$_}++;'

รับไฟล์อินพุต:

abc
def
abc
ghi
abc
def
abc
ghi
jkl

มันให้ผลผลิต:

abc
def
ghi
jkl

การกำหนดบรรทัด $ อยู่ที่ไหน
เกร็ก Leventhal

มันไม่ใช่ เนื่องจากไม่มีuse strict;หรือuse warnings;(จริง ๆ แล้วมันมีstrictความเกี่ยวข้องมากที่สุดที่นี่) จึงไม่มีการร้องเรียนเกี่ยวกับการใช้งาน%linesก่อนที่จะมีการกำหนด หากวิ่งด้วยความเข้มงวดจะต้องมีบรรทัดmy %lines;ก่อนลูป หมายเหตุเช่นกันว่าแฮชคือ%lines; องค์ประกอบหนึ่งของแฮชอ้างอิงโดยใช้$lines{$_}สัญกรณ์
Jonathan Leffler

ฉันคิดว่าsortวิธีแก้ปัญหาอาจดีกว่าสำหรับข้อมูลจำนวนมาก (OP เกี่ยวข้องกับ "การจัดเก็บไฟล์ทั้งหมดในหน่วยความจำ") sortจะทำการเรียงลำดับนอกแกนถ้าข้อมูลมีขนาดใหญ่กว่าหน่วยความจำที่มีอยู่
Kusalananda

0

สำหรับส่วนสุดท้ายของคำตอบที่กล่าวถึงใน: การพิมพ์บรรทัดที่ไม่ซ้ำกันโดย @Gilles เป็นคำตอบสำหรับคำถามนี้ฉันพยายามกำจัดความต้องการในการใช้แฮชสองตัว

วิธีนี้ใช้สำหรับ: ในการพิมพ์เฉพาะบรรทัดที่ไม่ซ้ำกันตามลำดับการปรากฏครั้งแรก:

awk '{counter[$0]++} END {for (line in counter) if (counter[line]==1) print line}'

ที่นี่ "ตัวนับ" จะเก็บจำนวนของแต่ละบรรทัดที่คล้ายกับที่ประมวลผลก่อนหน้านี้
ในตอนท้ายเราพิมพ์เฉพาะบรรทัดเหล่านั้นที่มีค่าตัวนับเป็น 1

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