Saya ingin menggabungkan dua blok garis di Vim, yaitu mengambil garis n..m
dan menambahkannya ke garis a..b
. Jika Anda lebih suka penjelasan kodesemu:[a[i] + b[i] for i in min(len(a), len(b))]
Contoh:
abc
def
...
123
45
...
harus menjadi
abc123
def45
Apakah ada cara yang bagus untuk melakukan ini tanpa melakukan copy & paste secara manual?
x
dengan bergabungx+2
?[a[i] + b[i] for i in min(len(a), len(b))]
Jawaban:
Anda tentu dapat melakukan semua ini dengan satu salin / tempel (menggunakan pemilihan blok-mode), tapi saya rasa bukan itu yang Anda inginkan.
Jika Anda ingin melakukan ini hanya dengan perintah Ex
akan berubah
ke
UPDATE: Sebuah jawaban dengan banyak upvotes ini layak mendapat penjelasan yang lebih menyeluruh.
Di Vim, Anda bisa menggunakan karakter pipa (
|
) untuk mengaitkan beberapa perintah Ex, sehingga di atas sama denganBanyak perintah Ex menerima rentang baris sebagai argumen awalan - dalam kasus di atas
5,8
sebelumdel
dan1,4
sebelums///
menentukan baris mana perintah beroperasi.del
menghapus garis yang diberikan. Itu dapat mengambil argumen register, tetapi ketika seseorang tidak diberikan, ia membuang baris ke register yang tidak disebutkan namanya@"
,, seperti menghapus dalam mode normal.let l=split(@")
kemudian memecah baris yang dihapus menjadi daftar, menggunakan pembatas default: whitespace. Untuk bekerja dengan baik pada input yang memiliki spasi putih di baris yang dihapus, seperti:kami perlu menentukan pembatas yang berbeda, untuk mencegah "pekerjaan" dari terbelah menjadi dua daftar elemen:
let l=split(@","\n")
.Akhirnya, dalam substitusi
s/$/\=remove(l,0)/
, kami mengganti akhir setiap baris ($
) dengan nilai ekspresiremove(l,0)
.remove(l,0)
mengubah daftarl
, menghapus dan mengembalikan elemen pertamanya. Ini memungkinkan kita mengganti baris yang dihapus sesuai urutan kita membacanya. Kami malah bisa mengganti baris yang dihapus dalam urutan terbalik dengan menggunakanremove(l,-1)
.sumber
s/\s*$/
bukans/$/
.:sil5,8del | let l=split(@") | sil1,4s/$/\=remove(l,0)/ | call histdel("/", -1) | nohls
tampaknya lebih baik karena membersihkan riwayat pencarian setelah berjalan. Dan itu tidak menunjukkan pesan "x lebih / kurang baris" yang mengharuskan saya untuk menekan enter.:help range
,:help :d
,:help :let
,:help split()
,:help :s
,:help :s\=
,:help remove()
.Perintah Ex elegan dan ringkas memecahkan masalah ini dapat diperoleh dengan menggabungkan
:global
,:move
dan:join
perintah. Dengan asumsi bahwa blok pertama dari garis dimulai pada baris pertama dari buffer, dan bahwa kursor terletak pada baris segera sebelum baris pertama dari blok kedua, perintahnya adalah sebagai berikut.Untuk penjelasan rinci tentang teknik ini, lihat jawaban saya untuk pertanyaan serupa " Vim paste -d '' perilaku di luar kotak? ”
sumber
E16: Invalid Range
- tapi tetap berhasil. Saat melepas1,
itu berfungsi tanpa kesalahan.:move
dan:join!
, atau apa yang''
dimaksud dengan argumen rentang (:help ''
) dan apa+
dan-
artinya sebagai pengubah kisaran (:help range
). Terima kasih!sil!
ke perintah.Untuk bergabung dengan blok garis, Anda harus melakukan langkah-langkah berikut:
jj
CTRL-v
$
CTRL-END
x
kk$
p
Gerakannya bukan yang terbaik (saya bukan ahli), tapi itu bekerja seperti yang Anda inginkan. Semoga akan ada versi yang lebih pendek.
Berikut adalah prasyarat agar teknik ini bekerja dengan baik:
abc
dandef
) memiliki panjang XOR yang samasumber
abc
dandef
panjangnya sama. Pilihan blok akan menjaga indentasi dari teks yang dihapus, jadi jika kursor berada pada garis pendek saat meletakkan teks, garis dimasukkan di antara huruf-huruf pada yang lebih panjang - dan spasi ditambahkan ke yang lebih pendek jika kursor berada pada garis yang lebih panjang. satu.:%s/ \+/ /g
set ve=all
seharusnya membantu, lihat vimdoc.sourceforge.net/htmldoc/options.html#'virtualedit 'Begini cara saya melakukannya (dengan kursor di baris pertama):
Anda perlu tahu dua hal:
Inilah yang terjadi:
qa
mencatat semuanya hingga selanjutnyaq
menjadi "buffer" dia
.ma
menciptakan tanda pada baris saat ini.:5<CR>
pergi ke grup berikutnya.y$
menarik sisa garis.'a
kembali ke tanda, atur lebih awal.$p
pasta di akhir baris.:5<CR>
kembali ke baris pertama grup kedua.dd
menghapusnya.'a
kembali ke sasaran.jq
turun satu baris, dan berhenti merekam.3@a
mengulangi tindakan untuk setiap baris (3 dalam kasus saya)sumber
[Enter]
setelah:5
kedua kali Anda mengetiknya atau ini tidak akan berhasil.:norm qama:5<CR>y$'a$p:5<CR>dd'ajq3@a
tetapi yang tampaknya hanya mengeksekusiq
.:let @a="ma:5^My$'a$p:5^Mdd'aj" | normal 4@a
, di mana^M
karakter diketik dengan menekan CTRL-V lalu Enter.Seperti disebutkan di tempat lain, pemilihan blok adalah jalan yang harus ditempuh. Tetapi Anda juga dapat menggunakan varian apa pun dari:
:!tail -n -6 % | paste -d '\0' % - | head -n 5
Metode ini bergantung pada baris perintah UNIX. The
paste
utilitas diciptakan untuk menangani semacam ini baris penggabungan.sumber
paste -d
Perilaku yang diinginkan ( seperti) dapat diimplementasikan dengan menggunakan perintah Vim pendek, seperti yang ditunjukkan dalam jawaban saya .Data sampel sama dengan rampion.
sumber
Saya tidak akan berpikir membuatnya terlalu rumit. Saya hanya akan mengatur virtualedit pada
(
:set virtualedit=all
)Pilih blok 123 dan semuanya di bawah.
Taruh setelah kolom pertama:
dan hapus beberapa ruang antara hingga 1 ruang:
sumber
gvV:'<,'>s/\s+//g
(vim harus secara otomatis memasukkan'<,'>
untuk Anda sehingga Anda tidak perlu mengetikkannya secara manual).Saya akan menggunakan pengulangan kompleks :)
Mengingat ini:
Dengan kursor di baris pertama, tekan berikut ini:
dan kemudian tekan
@a
(dan selanjutnya Anda dapat menggunakan@@
) sebanyak yang diperlukan.Anda harus berakhir dengan:
(Ditambah baris baru.)
Penjelasan:
qa
mulai merekam pengulangan yang kompleks dia
}
melompat ke baris kosong berikutnyajdd
menghapus baris berikutnya''
kembali ke posisi sebelum lompatan terakhirp
rekatkan baris yang dihapus di bawah yang saat inikJ
tambahkan baris saat ini ke akhir yang sebelumnyax
hapus spasi yangJ
menambahkan di antara garis-garis gabungan; Anda dapat menghilangkan ini jika Anda menginginkan ruangj
pergi ke baris berikutnyaq
akhiri rekaman berulang yang kompleksSetelah itu Anda akan menggunakan
@a
untuk menjalankan pengulangan kompleks yang disimpana
, dan kemudian Anda dapat menggunakannya@@
untuk menjalankan kembali pengulangan kompleks yang terakhir dijalankan.sumber
Ada banyak cara untuk mencapai hal ini. Saya akan menggabungkan dua blok teks menggunakan salah satu dari dua metode berikut.
misalkan blok pertama berada pada baris 1 dan blok ke-2 dimulai dari baris 10 dengan posisi awal kursor pada baris nomor 1.
(\ n berarti menekan tombol enter.)
dengan makro menggunakan perintah: salin, tempel dan gabung.
dengan makro menggunakan perintah pindahkan baris di nomor baris ke-n dan gabung.
sumber