Vim: bagaimana cara menghapus setiap baris kedua?

99

Bagaimana melakukannya di Vim:

SEBELUM:

aaa
bbb
ccc
ddd
eee
fff

SETELAH:

aaa
ccc
eee
brazh
sumber
Anda harus dapat menggunakan makro: oreillynet.com/mac/blog/2006/07/…
Mark Wilkins
Saya suka banyaknya jawaban untuk yang satu ini. Menyukai.
froggythefrog

Jawaban:

105

Anda dapat menggunakan makro untuk ini. Lakukan hal berikut.

  • Mulai dalam mode perintah.
  • Pergi ke awal file dengan menekan gg.
  • Tekan qq.
  • Klik panah bawah dan tekan ddsetelah.
  • Tekan q.
  • tekan 10000@q

PS: Untuk masuk ke mode perintah cukup tekan Escape beberapa kali.

rui
sumber
11
Dengan asumsi file Anda kurang dari 20.000 baris tentu saja :-)
paxdiablo
3
Sebenarnya Anda salah Michael. Ini bekerja dengan sempurna karena VI akan berhenti menjalankan makro segera setelah mencapai akhir file. Anda dapat dengan mudah mencobanya dengan contoh di atas.
rui
1
Seperti makro lainnya, Anda harus melakukannya dengan benar untuk pertama kalinya, tetapi setelah itu Anda dapat menerapkannya ke file apa pun hanya dengan mengetik 10000 @ q. Bagaimanapun saya percaya itu hanya masalah selera jadi saya pasti tidak akan memulai debat filosofis. :)
rui
3
Saya lebih suka menggunakan 'makro'. Dengan menggunakan makro, Anda 'menjelaskan' bagaimana Anda akan menyelesaikan satu tugas tertentu dan membiarkan VIM mengulanginya untuk Anda. RUI, saya lebih suka menggunakan 'j' daripada tombol panah.
SolutionYogi
4
:g/^/+ddari pengguna stackoverflow.com/users/254635/ib (di bawah) adalah cara yang lebih elegan untuk menyelesaikan masalah ini.
SergioAraujo
256

Cara elegan (dan efisien) untuk menyelesaikan tugas adalah dengan menjalankan :+deleteperintah yang menghapus baris setelah baris saat ini, di setiap baris menggunakan :globalperintah:

:g/^/+d
ib.
sumber
10
Mengapa jawaban ini tidak mendapatkan lebih banyak suara? Ini sangat bersih dan sederhana. Atau Anda dapat menghapus baris pertama dan menjalankan perintah di atas untuk menghapus semua baris ganjil.
Usagi
3
@Usagi: Terima kasih! Saya merasakan hal yang sama tentang itu. Dan ya, Anda benar sekali, :1d|g/^/+dmenghapus garis ganjil.
ib.
@Usagi Jawaban lain dipilih sebagai 'jawaban terbaik' 2 tahun sebelum jawabannya muncul. Selain itu, meskipun ini adalah solusi yang lebih elegan, ini bisa saja ditulis dengan cara yang lebih berguna (yaitu. Tidak disebutkan tentang ^ apa yang dilakukan, sementara makro mudah dipahami oleh siapa saja).
pengguna1271772
3
Maaf, tetapi tanpa penjelasan tentang bagaimana perintah itu melakukan perilaku yang diinginkan, saya tidak akan memberikan suara positif, dan sebaliknya lebih memilih jawaban yang diterima, karena saya mengerti bagaimana perintah itu mencapai tujuan. Itulah perbedaan antara memberi ikan dan mengajarinya cara memancing.
Gabe
3
Entahlah, jawaban ini membuat saya keluar dan belajar memancing dengan perintah: g (artinya, saya membuat Google halaman ini - vim.wikia.com/wiki/Power_of_g ).
ambil
67

Kita dapat menggunakan :normalatau :normmenjalankan perintah mode normal yang diberikan. Sumber.

:%norm jdd
Tadhg
sumber
15
Jawaban ini kurang mendapat perhatian, mungkin karena kurangnya penjelasan baik di sini maupun di contekan yang ditautkan, berantakan. perintah norma menjalankan perintah mode normal yang setara dengan huruf yang mengikutinya. Jadi di sini menjalankan j untuk turun satu baris, dan dd untuk menghapusnya. Ini dapat digeneralisasikan ke baris ke-X dengan menambahkan lebih banyak 'j' dalam kasus ini.
imoatama
5
dan% adalah singkatan dari 1, $ (jalankan perintah berikut dari baris 1 hingga akhir)
Lambart
3
Saya tertarik mengapa %norm ddjtidak berfungsi jika Anda ingin menghapus baris ganjil.
Cyker
10
:map ^o ddj^o
^o

Di sini ^ singkatan dari CTRL. Makro rekursif untuk menghapus satu baris setiap dua baris. Pilih dengan baik baris pertama Anda dan selesai.

Raoul Supercopter
sumber
8

dari arsip surat vim :

:let i=1 | while i <= line('$') | if (i % 2) | exe i . "delete" | endif | let i += 1 | endwhile

(Untuk diketik pada satu baris pada baris perintah vim, akan menghapus baris 1,3,5,7, ...)

Fortega
sumber
4
Maka saya lebih suka !perl -ne 'print unless $. % 2':-)
Alex Brasetvik
Dan, Alex, saya pasti lebih suka solusi saya daripada solusi Anda, tetapi yang ini patut dipertimbangkan karena ini adalah satu-satunya solusi yang masuk akal yang hanya menggunakan vim itu sendiri di sini.
Michael Krelin - hacker
Cara makro jauh lebih mudah.
trusktr
+1 karena fleksibilitas if (expression)yang juga berfungsi untuk setiap baris ketiga, dll.
Jens
5

Anda selalu dapat menyalurkan melalui perintah shell, yang berarti Anda dapat menggunakan bahasa skrip apa pun yang Anda suka:

:%!perl -nle 'print if $. % 2'

(atau gunakan "kecuali", bukan "jika", bergantung pada baris mana yang Anda inginkan)

ramping
sumber
Anda tidak perlu -lberalih ke Perl ... juga, menurut saya itu awksedikit lebih luas daripada Perl, meskipun sekarang ini tidak terlalu banyak, dan dapat melakukannya dengan lebih singkat:, :%!awk NR\%2atau :%!awk 1-NR\%2untuk baris lainnya.
singkat
4
:%!awk -- '++c\%2'

kalau tidak

:%!awk -- 'c++\%2'

tergantung bagian mana yang ingin Anda singkirkan.

Michael Krelin - peretas
sumber
Umm, kenapa tidak menggunakan NRvariabel yang sudah ada ?
singkat
Baik. Karena saya lupa tentang itu. ;-) Namun sebenarnya, varian yang "tepat" akan lebih panjang lagi dengan NR. Dan tidak akan ada dua rekan yang tampan .
Michael Krelin - hacker
:%!awk NR\%2atau :%!awk 1-NR\%2, seperti yang saya posting di komentar lain. Hampir tidak lagi.
singkat
1
1-NRlebih lama dari c++. Ya, saya tahu itu satu karakter. Seperti yang saya katakan - alasan sebenarnya adalah saya lupa tentang itu. Pokoknya, sepertinya orang tidak menghargai keindahan awk di sini.
Michael Krelin - hacker
Dan NRlebih pendek dari ++c:)
ephemient
3

Anda dapat menggunakan kemampuan pencarian dan penggantian Vim sendiri seperti: Letakkan kursor Anda di baris pertama, dan ketik dalam mode normal:

:.,/fff/s/\n.*\(\n.*\)/\1/g
  • Ini .,/fff/adalah kisaran untuk substitusi. Artinya "dari baris ini ke baris yang cocok dengan regex fff(dalam hal ini, baris terakhir).
  • s///adalah perintah pengganti. Itu mencari regex dan menggantikan setiap kemunculannya dengan string. Di gakhir berarti mengulangi substitusi selama regex tetap ditemukan.
  • Ekspresi reguler \n.*\(\n.*\)cocok dengan baris baru, lalu seluruh baris ( .*cocok dengan sejumlah karakter kecuali untuk baris baru), lalu baris baru dan baris lain. Tanda kurung \(dan \)menyebabkan ekspresi di dalamnya direkam, jadi kita bisa menggunakannya nanti menggunakan\1 .
  • \1 menyisipkan baris baru yang dikelompokkan dan baris setelahnya kembali, karena kami tidak ingin baris berikutnya hilang juga - kami hanya ingin mekanisme substitusi melewatinya sehingga kami tidak menghapusnya di penggantian berikutnya.

Dengan cara ini Anda dapat mengontrol rentang tempat Anda ingin menghapus dilakukan, dan Anda tidak perlu menggunakan alat eksternal apa pun.

Daniel Hershcovich
sumber
Atau $sebagai gantinya /fff/, untuk akhir file apa pun konten file tersebut.
singkat
3

Sebagai pendekatan lain, Anda juga bisa menggunakan python jika vim Anda mendukungnya.

:py import vim; cb = vim.current.buffer; b = cb[:]; cb[:] = b[::2]

b = cb[:]menyalin sementara semua baris di buffer saat ini ke b. b[::2]mendapatkan setiap baris kedua dari buffer dan menugaskannya ke seluruh buffer saat ini cb[:]. Salinan ke bdiperlukan karena objek buffer tampaknya tidak mendukung sintaksis slice yang diperluas.

Ini mungkin bukan "cara vim", tetapi bisa lebih mudah diingat jika Anda mengenal python.

qzr
sumber
2

Untuk menghapus garis ganjil (1,3,5, ..) -> :%s/\(.*\)\n\(.*\)\n/\2\r/g

Untuk menghapus garis genap (2,4,6, ..) -> :%s/\(.*\)\n.*\n/\1\r/g

Mencari teks (membentuk baris pertama) diikuti dengan karakter baris baru dan beberapa teks lagi (membentuk baris kedua) diikuti dengan karakter baris baru lainnya dan mengganti di atas dengan kecocokan pertama (baris ganjil) atau kecocokan kedua (baris genap) diikuti dengan kereta kembali.

kartik kailas
sumber
0

Panggil sed:

:% !sed -e '2~2 d'

^^^^                  pipe file through a shell command
    ^^^^^^            the command is sed, and -e describes an expression as parameter
            ^^^^^     starting with the second line, delete every second line
asdmin
sumber
-1

larutan

Anda dapat mencoba ini di vim

:1,$-1g/^/+1d

edit

Saya akan mencoba lebih jelas (dua bagian)

bagian pertama rentang pilihan ( :from,to)
bagian kedua tindakan ( dhapus)

  • kisaran jika dari baris pertama ke baris terakhir tetapi satu baris ( :1,$-1)
  • globaly ( g) delete ( +1d) baris berikutnya

Anda dapat mencoba untuk pindah ke baris pertama dari file Anda dan mengeksekusi :+1dAnda akan melihat baris berikutnya menghilang

Saya tahu ini berlumpur, tetapi vim dan berhasil

anjing
sumber
Jelas seperti lumpur. Terima kasih!
Henry Henrinson