Menghapus baris duplikat di vi?

123

Saya memiliki file teks yang berisi daftar panjang entri (satu di setiap baris). Beberapa di antaranya adalah duplikat, dan saya ingin tahu apakah mungkin (dan jika demikian, bagaimana) menghapus duplikat apa pun. Saya tertarik melakukan ini dari dalam vi / vim, jika memungkinkan.

Sydius
sumber
1
Sepertinya duplikat stackoverflow.com/questions/746689/…
Nathan Fellman
4
Yang ini berumur 1 tahun; yang satu itu 10 bulan. Jadi, sebaliknya.
Sydius
Konsensus @Sydius sekarang adalah memprioritaskan jumlah suara positif (yang juga Anda miliki lebih banyak): meta.stackexchange.com/questions/147643/… Dan itu bukan duplikat, yang tidak menyebutkan Vim :-)
Ciro Santilli 郝海东 冠状 病六四 事件 法轮功

Jawaban:

269

Jika Anda setuju dengan penyortiran file Anda, Anda dapat menggunakan:

:sort u
Brian Carper
sumber
6
Ini sangat cantik. Terima kasih!
Shrayas
8
Jika pengurutan tidak dapat diterima, gunakan :%!uniquntuk menghapus entri duplikat tanpa mengurutkan file.
cryptic0
setelah Anda menggunakan perintah, seluruh file berubah? bagaimana kamu kembali? Saya telah menyimpan file karena kesalahan ... salah saya
nilon
Cukup gunakan perintah urungkan Vim :u
adampasz
25

Coba ini:

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

Ini mencari baris apa pun segera diikuti oleh satu atau lebih salinan dari dirinya sendiri, dan menggantinya dengan satu salinan.

Buat salinan file Anda sebelum Anda mencobanya. Ini belum teruji.

Sean
sumber
1
@hop Terima kasih telah mengujinya untuk saya. Saya tidak memiliki akses ke vim saat itu.
Sean
2
ini menyoroti semua baris duplikat untuk saya tetapi tidak menghapus, apakah saya melewatkan satu langkah di sini?
ak85
Saya cukup yakin ini juga akan menyoroti sebuah baris yang diikuti oleh sebuah baris yang memiliki "awalan" yang sama tetapi lebih panjang.
hippietrail
3
Satu-satunya masalah dengan ini adalah jika Anda memiliki beberapa duplikat (3 atau lebih dari baris yang sama), Anda harus menjalankan ini berkali-kali sampai semua dup hilang karena ini hanya menghapusnya satu set dup pada satu waktu.
horta
2
Kelemahan lain dari ini: ini tidak akan berfungsi kecuali garis duplikat Anda sudah bersebelahan. Menyortir lebih dulu akan menjadi salah satu cara untuk memastikan mereka bersebelahan. Pada titik itu, jawaban lain mungkin lebih baik.
horta
23

Dari baris perintah lakukan saja:

sort file | uniq > file.new
Kevin
sumber
1
Ini sangat berguna bagi saya untuk file besar. Terima kasih!
Rafid
1
Tidak bisa mendapatkan jawaban yang diterima untuk bekerja, karena :sort utergantung di file besar saya. Ini bekerja dengan sangat cepat dan sempurna. Terima kasih!
Tgsmith61591
1
'uniq' is not recognized as an internal or external command, operable program or batch file.
hippietrail
1
Ya - Saya mencoba teknik ini pada file 2,3 GB, dan ternyata sangat cepat.
DanM
@hippietrail Anda menggunakan Windows PC? Mungkin Anda bisa menggunakan cygwin.
12431234123412341234123
8

awk '!x[$0]++' yourfile.txtjika Anda ingin mempertahankan urutan (yaitu, penyortiran tidak dapat diterima). Untuk memanggilnya dari vim, :!bisa digunakan.

Rovin Bhandari
sumber
4
Ini bagus! Tidak perlu menyortir persis seperti yang saya cari!
Cometsong
6
g/^\(.*\)$\n\1/d

Bekerja untuk saya di Windows. Garis harus diurutkan terlebih dahulu.

Bridgey
sumber
1
Ini akan menghapus sebuah baris yang mengikuti sebuah baris yang merupakan awalannya: aaaadiikuti oleh aaaabbakan menghapus secara aaaakeliru.
hippietrail
5

Saya akan menggabungkan dua jawaban di atas:

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

1G
!Gsort
1G
!Guniq

Jika Anda tertarik untuk melihat berapa banyak baris duplikat yang dihapus, gunakan control-G sebelum dan sesudah untuk memeriksa jumlah baris yang ada di buffer Anda.

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

Pilih garis dalam mode garis visual ( Shift+ v), lalu :!uniq. Itu hanya akan menangkap duplikat yang datang satu demi satu.

derobert
sumber
1
Hanya untuk dicatat ini hanya akan bekerja pada komputer dengan program uniq diinstal yaitu Linux, Mac, Freebsd dll
anteatersa
Ini akan menjadi jawaban terbaik bagi mereka yang tidak perlu menyortir. Dan jika Anda pengguna windows, pertimbangkan untuk mencoba Cygwin atau MSYS.
fx-kirin
1

Mengenai bagaimana Uniq dapat diimplementasikan di VimL, ​​cari Uniq di plugin yang saya kelola . Anda akan melihat berbagai cara untuk menerapkannya yang diberikan di milis Vim.

Jika tidak, :sort umemang cara untuk pergi.

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

atau

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

ini jawaban saya untuk Anda, ini dapat menghapus beberapa baris duplikat dan hanya menyimpan satu tidak menghapus!

cn8341
sumber
0

Saya akan menggunakan !}uniq, tetapi itu hanya berfungsi jika tidak ada baris kosong.

Untuk setiap baris dalam sebuah file digunakan: :1,$!uniq.

Chris Dodd
sumber
0

Versi ini hanya menghapus garis berulang yang bersinggungan. Maksud saya, hanya menghapus baris berulang yang berurutan. Menggunakan peta yang diberikan, fungsinya tidak mengacaukan garis kosong. Tetapi jika mengubah REGEX agar sesuai dengan awal baris ^itu juga akan menghapus duplikat baris kosong.

" 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>
SergioAraujo
sumber
0

Metode alternatif yang tidak menggunakan vi / vim (untuk file yang sangat besar), adalah dari baris perintah Linux gunakan sort dan uniq:

sort {file-name} | uniq -u
william-1066
sumber
0

Ini berhasil bagi saya untuk keduanya .csvdan.txt

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

Penjelasan: Bagian pertama dari perintah mencetak baris unik dan bagian kedua yaitu setelah panah tengah adalah untuk menyimpan keluaran dari bagian pertama.

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

>

<newFileName>

paul
sumber