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.
Cara elegan (dan efisien) untuk menyelesaikan tugas adalah dengan menjalankan :+deleteperintah yang menghapus baris setelah baris saat ini, di setiap baris menggunakan :globalperintah:
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.
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.
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)
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.
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.
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.
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.
:% !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
Jawaban:
Anda dapat menggunakan makro untuk ini. Lakukan hal berikut.
gg
.qq
.dd
setelah.q
.10000@q
PS: Untuk masuk ke mode perintah cukup tekan Escape beberapa kali.
sumber
:g/^/+d
dari pengguna stackoverflow.com/users/254635/ib (di bawah) adalah cara yang lebih elegan untuk menyelesaikan masalah ini.Cara elegan (dan efisien) untuk menyelesaikan tugas adalah dengan menjalankan
:+delete
perintah yang menghapus baris setelah baris saat ini, di setiap baris menggunakan:global
perintah:sumber
:1d|g/^/+d
menghapus garis ganjil.Kita dapat menggunakan
:normal
atau:norm
menjalankan perintah mode normal yang diberikan. Sumber.sumber
%norm ddj
tidak berfungsi jika Anda ingin menghapus baris ganjil.Di sini ^ singkatan dari CTRL. Makro rekursif untuk menghapus satu baris setiap dua baris. Pilih dengan baik baris pertama Anda dan selesai.
sumber
dari arsip surat vim :
(Untuk diketik pada satu baris pada baris perintah vim, akan menghapus baris 1,3,5,7, ...)
sumber
!perl -ne 'print unless $. % 2'
:-)if (expression)
yang juga berfungsi untuk setiap baris ketiga, dll.Anda selalu dapat menyalurkan melalui perintah shell, yang berarti Anda dapat menggunakan bahasa skrip apa pun yang Anda suka:
(atau gunakan "kecuali", bukan "jika", bergantung pada baris mana yang Anda inginkan)
sumber
-l
beralih ke Perl ... juga, menurut saya ituawk
sedikit lebih luas daripada Perl, meskipun sekarang ini tidak terlalu banyak, dan dapat melakukannya dengan lebih singkat:,:%!awk NR\%2
atau:%!awk 1-NR\%2
untuk baris lainnya.kalau tidak
tergantung bagian mana yang ingin Anda singkirkan.
sumber
NR
variabel yang sudah ada ?:%!awk NR\%2
atau:%!awk 1-NR\%2
, seperti yang saya posting di komentar lain. Hampir tidak lagi.1-NR
lebih lama daric++
. 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.NR
lebih pendek dari++c
:)Anda dapat menggunakan kemampuan pencarian dan penggantian Vim sendiri seperti: Letakkan kursor Anda di baris pertama, dan ketik dalam mode normal:
.,/fff/
adalah kisaran untuk substitusi. Artinya "dari baris ini ke baris yang cocok dengan regexfff
(dalam hal ini, baris terakhir).s///
adalah perintah pengganti. Itu mencari regex dan menggantikan setiap kemunculannya dengan string. Dig
akhir berarti mengulangi substitusi selama regex tetap ditemukan.\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.
sumber
$
sebagai gantinya/fff/
, untuk akhir file apa pun konten file tersebut.Sebagai pendekatan lain, Anda juga bisa menggunakan python jika vim Anda mendukungnya.
b = cb[:]
menyalin sementara semua baris di buffer saat ini keb
.b[::2]
mendapatkan setiap baris kedua dari buffer dan menugaskannya ke seluruh buffer saat inicb[:]
. Salinan keb
diperlukan karena objek buffer tampaknya tidak mendukung sintaksis slice yang diperluas.Ini mungkin bukan "cara vim", tetapi bisa lebih mudah diingat jika Anda mengenal python.
sumber
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.
sumber
Panggil sed:
sumber
larutan
Anda dapat mencoba ini di vim
edit
Saya akan mencoba lebih jelas (dua bagian)
bagian pertama rentang pilihan (
:from,to
)bagian kedua tindakan (
d
hapus):1,$-1
)g
) delete (+1d
) baris berikutnyaAnda dapat mencoba untuk pindah ke baris pertama dari file Anda dan mengeksekusi
:+1d
Anda akan melihat baris berikutnya menghilangSaya tahu ini berlumpur, tetapi vim dan berhasil
sumber