Ketika saya mencari dengan /
perintah mode Normal:
/\vSEARCHTERM
Vim memulai pencarian dari posisi kursor dan berlanjut ke bawah, melingkari ke atas. Namun, ketika saya mencari dan mengganti menggunakan :substitute
perintah:
:%s/\vBEFORE/AFTER/gc
Vim dimulai dari bagian atas file.
Apakah ada cara untuk membuat Vim melakukan pencarian dan penggantian mulai dari posisi kursor dan membungkus ke atas setelah mencapai akhir?
\vpattern
- Pola 'sangat ajaib': karakter non-alfanumerik diinterpretasikan sebagai simbol regex khusus (tidak perlu melarikan diri)%
? Saya tidak melihat penggunaan yang masuk akal untuk itu Anda akan melalui seluruh file.Jawaban:
1. Tidak sulit untuk mencapai perilaku menggunakan substitusi dua langkah:
Pertama, perintah substitusi dijalankan untuk setiap baris mulai dari yang sekarang hingga akhir file:
Kemudian,
:substitute
perintah itu diulangi dengan pola pencarian, string pengganti, dan flag yang sama, menggunakan:&
perintah (lihat:help :&
):Namun, yang terakhir melakukan substitusi pada rentang baris dari baris pertama file ke baris di mana tanda konteks sebelumnya telah ditetapkan, minus satu. Karena
:substitute
perintah pertama menyimpan posisi kursor sebelum memulai penggantian yang sebenarnya, baris yang dialamatkan oleh''
adalah baris yang ada sebelum perintah substitusi itu dijalankan. (''
Alamat mengacu pada tanda'
palsu; lihat:help :range
dan:help ''
untuk detailnya.)Perhatikan bahwa perintah kedua (setelah
|
pemisah perintah — lihat:help :bar
) tidak memerlukan perubahan apa pun saat pola atau bendera diubah pada yang pertama.2. Untuk menyimpan beberapa pengetikan, untuk memunculkan kerangka dari perintah substitusi di atas pada baris perintah, seseorang dapat mendefinisikan pemetaan mode-Normal, seperti:
Bagian belakang
<c-b><right><right><right><right>
diperlukan untuk memindahkan kursor ke awal baris perintah (<c-b>
) dan kemudian empat karakter ke kanan (<right>
× 4), sehingga meletakkannya di antara dua tanda garis miring pertama, siap bagi pengguna untuk mulai mengetik pola pencarian . Setelah pola yang diinginkan dan penggantinya siap, perintah yang dihasilkan dapat dijalankan dengan menekan Enter.(Seseorang mungkin mempertimbangkan untuk memiliki
//
daripada///
dalam pemetaan di atas, jika seseorang lebih memilih untuk mengetik pola, kemudian ketik garis miring pemisah itu sendiri, diikuti dengan string pengganti, daripada menggunakan panah kanan untuk memindahkan kursor ke atas garis miring pemisah yang sudah ada mulai bagian pengganti.)sumber
:noremap <leader>R :,$s///gc\|1,''-&&<c-b><right><right><right><right>
. Ini menempatkan:,$s///gc|1,''-&&
ke dalam baris perintah dengan kursor di antara dua tanda garis miring pertama. Setelah Anda mengetik pola dan penggantian yang diinginkan, Anda dapat menjalankan perintah yang dihasilkan dengan menekan Enter .Anda sudah menggunakan range
%
, yang merupakan singkatan1,$
dari keseluruhan file. Untuk beralih dari baris saat ini ke akhir yang Anda gunakan.,$
. Periode berarti baris saat ini dan$
berarti baris terakhir. Jadi perintahnya adalah:Tetapi garis
.
atau arus dapat diasumsikan karena itu dapat dihilangkan:Untuk bantuan lebih lanjut lihat
sumber
10:s/pattern/replace/gc
%
adalah jalan pintas untuk1,$
(Vim help =>
:help :%
sama dengan 1, $ (seluruh file).).
adalah posisi kursor yang dapat Anda lakukanUntuk mengganti dari awal dokumen sampai kursor
dll
Saya sangat menyarankan Anda membaca manual tentang range
:help range
karena hampir semua perintah bekerja dengan range.sumber
Saya AKHIRNYA menemukan solusi untuk fakta bahwa berhenti dari pencarian membungkus awal file tanpa menulis fungsi yang sangat besar ...
Anda tidak akan percaya berapa lama saya harus memikirkan ini. Cukup tambahkan prompt apakah akan membungkus: jika pengguna menekan
q
lagi, jangan membungkus. Jadi pada dasarnya, hentikan penelusuran dengan mengetukqq
alih-alihq
! (Dan jika Anda ingin membungkus, cukup ketiky
.)Saya sebenarnya telah memetakan ini ke hotkey. Jadi, misalnya, jika Anda ingin mencari dan mengganti setiap kata di bawah kursor, mulai dari posisi saat ini, dengan
q*
:sumber
q
,l
atau Esc ) dan tidak ingin melanjutkan dari atas, Anda sudah dapat menekanq
atau Esc lagi untuk segera keluar dari perintah kedua. Artinya, penambahan prompt yang diusulkan tampaknya secara efektif menduplikasi fungsionalitas yang sudah ada.yyyq
, melanjutkan pengeditan, tanpa lompatan yang membingungkan. Tapiyyyqq
hampir sama baiknya, jika Anda menganggap ketukan dua kali cukup banyak satu ketukan dalam hal kemudahan penggunaan.q
untuk kedua kalinya). Yang terakhir meninggalkan kursor pada kemunculan terakhir yang diganti (tepat sebelum yang pertamaq
ditekan).norm!``
perintah::,$s/BEFORE/AFTER/gc|1,''-&&|norm!``
.Berikut adalah sesuatu yang sangat kasar yang membahas kekhawatiran tentang membungkus pencarian dengan pendekatan dua langkah (
:,$s/BEFORE/AFTER/gc|1,''-&&
) atau dengan perantara "Lanjutkan di awal file?" pendekatan:Fungsi ini menggunakan beberapa peretasan untuk memeriksa apakah kita harus menyelesaikannya di atas:
sumber
Saya terlambat ke pesta, tetapi saya terlalu sering mengandalkan jawaban stackoverflow yang terlambat untuk tidak melakukannya. Saya mengumpulkan petunjuk tentang reddit dan stackoverflow, dan opsi terbaik adalah menggunakan
\%>...c
pola dalam pencarian, yang hanya cocok setelah kursor Anda.Meskipun demikian, itu juga mengacaukan pola untuk langkah penggantian berikutnya, dan sulit untuk diketik. Untuk mengatasi efek tersebut, fungsi kustom harus memfilter pola pencarian setelahnya, sehingga menyetel ulang. Lihat di bawah.
Saya telah bersaing dengan diri saya sendiri dengan pemetaan yang menggantikan kemunculan berikutnya dan melompat ke kejadian berikutnya setelahnya, dan tidak lebih (bagaimanapun juga tujuan saya). Saya yakin, dengan membangun ini, substitusi global dapat dilakukan. Perlu diingat saat mengerjakan solusi yang bertujuan pada sesuatu seperti
:%s/.../.../g
itu, pola di bawah menyaring kecocokan di semua baris yang tersisa ke posisi kursor - tetapi dibersihkan setelah substitusi tunggal selesai, jadi efek itu langsung hilang setelahnya, lompat ke pertandingan berikutnya dan dengan demikian dapat menjalankan semua pertandingan satu per satu.fun! g:CleanColFromPattern(prevPattern) return substitute(a:prevPattern, '\V\^\\%>\[0-9]\+c', '', '') endf nmap <F3>n m`:s/\%><C-r>=col(".")-1<CR>c<C-.r>=g:CleanColFromPattern(getreg("/"))<CR>/~/&<CR>:call setreg("/", g:CleanColFromPattern(getreg("/")))<CR>``n
sumber