การลบแถวที่ซ้ำกันใน vi?


124

ฉันมีไฟล์ข้อความที่มีรายการยาว ๆ (หนึ่งรายการในแต่ละบรรทัด) บางส่วนเป็นรายการที่ซ้ำกันและฉันต้องการทราบว่าเป็นไปได้หรือไม่ (ถ้าเป็นเช่นนั้น) จะลบรายการที่ซ้ำกันได้อย่างไร ฉันสนใจที่จะทำสิ่งนี้จากภายใน vi / vim ถ้าเป็นไปได้


1
ดูเหมือนว่าจะซ้ำกันของstackoverflow.com/questions/746689/…
Nathan Fellman

4
อันนี้ 1 ปี; อันนั้นคือ 10 เดือน ดังนั้นวิธีอื่น ๆ
Sydius

@Sydius ฉันทามติในตอนนี้คือการจัดลำดับความสำคัญของการนับคะแนนโหวต (ซึ่งคุณมีมากกว่านี้): meta.stackexchange.com/questions/147643/…และสิ่งเหล่านี้ไม่ใช่รายการที่ซ้ำกันนั่นไม่ได้กล่าวถึง Vim :-)
Ciro Santilli 郝海东冠状病六四事件法轮功

คำตอบ:


271

หากคุณพอใจกับการจัดเรียงไฟล์ของคุณคุณสามารถใช้:

:sort u

6
นี่มันสวยมาก ขอบคุณ!
Shrayas

8
หากไม่สามารถจัดเรียงได้ให้ใช้:%!uniqเพียงแค่ลบรายการที่ซ้ำกันโดยไม่ต้องเรียงไฟล์
cryptic0

เมื่อคุณใช้คำสั่งไฟล์ทั้งหมดจะเปลี่ยนแปลง? คุณจะกลับไปอย่างไร ฉันบันทึกไฟล์โดยไม่ได้ตั้งใจ ... ฉันไม่ดี
nilon


25

ลองสิ่งนี้:

:%s/^\(.*\)\(\n\1\)\+$/\1/

โดยจะค้นหาบรรทัดใด ๆ ตามด้วยสำเนาของตัวเองหนึ่งชุดหรือมากกว่านั้นทันทีและแทนที่ด้วยสำเนาเดียว

ทำสำเนาไฟล์ของคุณก่อนที่คุณจะลองใช้ ยังไม่ทดลอง


1
@hop ขอบคุณสำหรับการทดสอบสำหรับฉัน ฉันไม่สามารถเข้าถึงกลุ่มได้ในเวลานั้น
Sean

2
ความสูงนี้แสดงให้เห็นบรรทัดที่ซ้ำกันทั้งหมดสำหรับฉัน แต่ไม่ได้ลบฉันพลาดขั้นตอนที่นี่หรือไม่?
ak85

ฉันค่อนข้างมั่นใจว่านี่จะเน้นบรรทัดตามด้วยบรรทัดที่มี "คำนำหน้า" เหมือนกัน แต่ยาวกว่า
hippietrail

3
ปัญหาเดียวในเรื่องนี้คือถ้าคุณมีรายการซ้ำหลายรายการ (3 บรรทัดขึ้นไปในบรรทัดเดียวกัน) คุณต้องเรียกใช้หลาย ๆ ครั้งจนกว่าการทำซ้ำทั้งหมดจะหายไปเนื่องจากจะลบการทำซ้ำทีละชุดเท่านั้น
horta

2
ข้อเสียเปรียบอีกประการหนึ่ง: สิ่งนี้จะไม่ทำงานเว้นแต่บรรทัดที่ซ้ำกันของคุณจะอยู่ติดกัน การเรียงลำดับก่อนอื่นจะเป็นวิธีหนึ่งในการทำให้แน่ใจว่าพวกเขาอยู่ติดกัน เมื่อถึงจุดนั้นคำตอบอื่น ๆ น่าจะดีกว่า
horta

23

จากบรรทัดคำสั่งให้ทำ:

sort file | uniq > file.new

1
สิ่งนี้มีประโยชน์มากสำหรับฉันสำหรับไฟล์ขนาดใหญ่ ขอบคุณ!
Rafid

1
ไม่สามารถรับคำตอบที่เป็นที่ยอมรับในการทำงานเหมือนที่:sort uแขวนอยู่บนไฟล์ขนาดใหญ่ของฉัน สิ่งนี้ทำงานได้อย่างรวดเร็วและสมบูรณ์แบบ ขอบคุณ!
Tgsmith61591

1
'uniq' is not recognized as an internal or external command, operable program or batch file.
hippietrail

1
ใช่ - ฉันลองใช้เทคนิคนี้กับไฟล์ 2.3 GB แล้วและมันเร็วมากอย่างน่าตกใจ
DanM

@hippietrail คุณอยู่บน Windows PC? บางทีคุณอาจใช้ cygwin
12431234123412341234123

8

awk '!x[$0]++' yourfile.txtหากคุณต้องการรักษาคำสั่งซื้อ (กล่าวคือไม่ยอมรับการเรียงลำดับ) ในการเรียกใช้จากกลุ่ม:!สามารถใช้ได้


4
น่ารักขนาดนี้! ไม่จำเป็นต้องเรียงลำดับเป็นว่าสิ่งที่ฉันกำลังมองหา!
Cometsong

6
g/^\(.*\)$\n\1/d

ใช้ได้กับฉันบน Windows ต้องเรียงลำดับเส้นก่อน


1
การดำเนินการนี้จะลบบรรทัดที่อยู่ถัดจากบรรทัดซึ่งเป็นคำนำหน้า: aaaaตามด้วยaaaabbจะลบaaaaผิดพลาด
hippietrail

5

ฉันจะรวมสองคำตอบข้างต้น:

go to head of file
sort the whole file
remove duplicate entries with uniq

1G
!Gsort
1G
!Guniq

หากคุณสนใจที่จะดูจำนวนบรรทัดที่ซ้ำกันถูกลบออกให้ใช้ control-G ก่อนและหลังเพื่อตรวจสอบจำนวนบรรทัดที่มีอยู่ในบัฟเฟอร์ของคุณ


1
'uniq' is not recognized as an internal or external command, operable program or batch file.
hippietrail

3

เลือกสายในโหมดภาพบรรทัด ( Shift+ v) :!uniqแล้ว นั่นจะจับเฉพาะรายการที่ซ้ำกันซึ่งเกิดขึ้นทีละรายการ


1
โปรดทราบว่าสิ่งนี้จะใช้ได้เฉพาะกับคอมพิวเตอร์ที่ติดตั้งโปรแกรม uniq เช่น Linux, Mac, Freebsd ฯลฯ
anteatersa

นี่จะเป็นคำตอบที่ดีที่สุดสำหรับผู้ที่ไม่ต้องการการเรียงลำดับ และถ้าคุณเป็นผู้ใช้ windows ให้ลองใช้ Cygwin หรือ MSYS
fx-kirin

1

เกี่ยวกับวิธีการใช้งาน Uniq ใน VimL ให้ค้นหา Uniq ในปลั๊กอินที่ฉันดูแลอยู่อยู่ คุณจะเห็นวิธีต่างๆในการใช้งานที่ให้ไว้ในรายชื่อผู้รับจดหมายเป็นกลุ่ม

มิฉะนั้น:sort uจะเป็นหนทางไป


0
:%s/^\(.*\)\(\n\1\)\+$/\1/gec

หรือ

:%s/^\(.*\)\(\n\1\)\+$/\1/ge

นี่คือคำตอบของฉันสำหรับคุณมันสามารถลบบรรทัดที่ซ้ำกันหลายบรรทัดและเก็บไว้เพียงบรรทัดเดียวเท่านั้นที่จะไม่ลบ!


0

ฉันจะใช้!}uniqแต่จะใช้ได้ก็ต่อเมื่อไม่มีบรรทัดว่าง

สำหรับทุกบรรทัดในไฟล์ให้ใช้: :1,$!uniq.


0

เวอร์ชันนี้จะลบเฉพาะบรรทัดซ้ำ ๆ ที่ต่อเนื่องกัน ฉันหมายถึงลบบรรทัดที่ซ้ำกันเท่านั้น การใช้แผนที่ที่กำหนดฟังก์ชันโน้ตจะยุ่งกับเส้นว่าง แต่ถ้าเปลี่ยน REGEX ให้ตรงกับจุดเริ่มต้นของบรรทัด^จะเป็นการลบบรรทัดว่างที่ซ้ำกันออกไปด้วย

" function to delete duplicate lines
function! DelDuplicatedLines()
    while getline(".") == getline(line(".") - 1)
        exec 'norm! ddk'
    endwhile
    while getline(".") == getline(line(".") + 1)
        exec 'norm! dd'
    endwhile
endfunction
nnoremap <Leader>d :g/./call DelDuplicatedLines()<CR>

0

วิธีอื่นที่ไม่ใช้ vi / vim (สำหรับไฟล์ขนาดใหญ่มาก) มาจากบรรทัดคำสั่ง Linux use sort และ uniq:

sort {file-name} | uniq -u

0

สิ่งนี้ใช้ได้ผลกับฉันทั้ง.csvและ.txt

awk '!seen[$0]++' <filename> > <newFileName>

คำอธิบาย: ส่วนแรกของคำสั่งจะพิมพ์แถวที่ไม่ซ้ำกันและส่วนที่สองคือหลังจากลูกศรกลางคือการบันทึกผลลัพธ์ของส่วนแรก

awk '!seen[$0]++' <filename>

>

<newFileName>

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