Mirip dengan jawaban di https://vi.stackexchange.com/a/818/227 , Anda dapat menggunakan perintah global.
Dengannya Anda dapat menginstruksikan vim untuk mencari garis yang cocok dengan suatu pola, dan kemudian melakukan perintah di atasnya.
Dalam kasus Anda, Anda ingin menambahkan teks ke baris yang dimulai dengan "Level N:", sehingga perintah global kami bisa
:g/^Level \d:/{COMMANDS}
Menggunakan perintah pengganti (penggantian ekspresi reguler) untuk perintah
Perintahnya lebih menyenangkan. Saya biasanya suka melakukan penggantian ekspresi reguler untuk hal-hal seperti ini, karena mudah digunakan variabel.
Contoh untuk pertanyaan Anda
:let i = 1 | g/^Level \d:/s/^/\=printf("%02d ", i)/ | let i = i+1
Bagaimana itu bekerja
Di bagian penggantian perintah substitusi dapat berupa ekspresi.
Hal pertama yang akan kita lakukan adalah mengatur variabel i
menjadi angka awal. Saya memilih 1, tetapi nomor berapa pun akan berhasil.let i = 1
Kemudian kami menjalankan perintah global kami, yang membuat kami melakukan tindakan pada baris yang cocok. g/^Level \d:/
Kami akan meminta perintah global kami memasukkan nilai dan meningkatkan penghitung kami menggunakan perintah substitusi dan perintah let. s/^/\=printf("%02d ", i)/ | let i = i+1
Ekspresi reguler perintah substitusi menemukan awal baris ^
dan menggantinya dengan ekspresi, dan ekspresi kita akan menjadi hasil dari cetakan yang diformat. Seperti dalam bahasa C, printf vim mengambil parameter format. %02d
berarti mengonversi argumen seolah-olah itu angka desimal d
, menempati setidaknya 2 spasi 2
dan pad dengan 0 0
. Untuk detail dan opsi konversi lainnya (termasuk pemformatan titik mengambang), lihat :help printf
. Kami memberikan printf variabel penghitungan kami i
dan itu memberi kami 01
pertama kali, 02
kedua kalinya, dll. Ini digunakan oleh perintah substitusi untuk mengganti awal baris, secara efektif memasukkan hasil printf di awal.
Perhatikan bahwa saya menempatkan spasi setelah d: "%02d "
. Anda tidak menanyakannya dalam pertanyaan (dan saya tidak melihat contoh output), tetapi saya curiga Anda ingin memisahkan nomor dari kata "Level". Hapus spasi dari string yang diberikan ke printf agar angka yang dimasukkan tepat di sebelah L di Level.
Akhirnya, itu let i = i + 1
menambah penghitung kami setelah setiap penggantian.
Ini dapat diterapkan secara umum untuk mengganti bagian-bagian garis yang cocok dengan kriteria lain dengan data fungsional yang arbitrer.
Menggunakan perintah normal gabungan
Ini bagus untuk penyisipan sederhana atau pengeditan kompleks. Seperti halnya dengan pengganti, kami akan menggunakan global untuk mencocokkan, tetapi alih-alih substitusi ekspresi reguler, kami akan menjalankan serangkaian operasi seolah diketik oleh pengguna.
Contoh untuk pertanyaan Anda
:let i = 1 | g/^Level \d:/execute "normal! I" . printf("%02d ", i) | let i = i+1
Bagaimana itu bekerja
Nilai yang digunakan sangat mirip dengan pengganti (kami masih menggunakan printf untuk memformat nomor kami untuk membuatnya 0 diisi dengan 2 digit), tetapi operasinya berbeda.
Di sini kita menggunakan perintah eksekusi, yang mengambil string dan menjalankan string sebagai perintah ex ( :help :exe
). Kami membuat string yang menggabungkan "normal! I" dengan data kami, yang akan menjadi "normal! I01" pertama kali dan "normal! I02" kedua kalinya, dll.
The normal
perintah melakukan operasi seperti dalam mode normal. Dalam contoh ini, perintah normal kita adalah I
, yang menyisipkan di awal baris. Jika kita menggunakannya dd
akan menghapus baris, o
akan membuka baris baru setelah baris yang cocok. Seolah-olah Anda mengetik I
(atau operasi lainnya) sendiri dalam mode normal. kami menggunakan !
after normal
untuk memastikan tidak ada pemetaan yang menghalangi jalan kami. Lihat :help :normal
.
Apa yang dimasukkan kemudian adalah nilai printf kami, seperti pada contoh pertama menggunakan pengganti.
Metode ini bisa lebih bagus daripada regex, karena Anda dapat melakukan hal-hal seperti execute "normal! ^2wy" . i . "th$p"
, yang akan pergi ke awal teks ^
, bergerak maju 2 kata 2w
, menarik sampai karakter 'h' y" . i . "th
, pindah ke akhir baris $
, dan tempel p
.
Ini hampir seperti menjalankan makro, tetapi sebenarnya tidak menggunakan register dan dapat menggabungkan string dari ekspresi apa pun. Saya menemukan ini sangat kuat.
Pendekatan di mana setiap level memiliki counter sendiri
Anda mungkin ingin setiap level mendapatkan penghitungnya sendiri. Jika Anda mengetahui jumlah maksimum level sebelumnya, Anda dapat melakukan hal berikut (menambahkan kode tambahan untuk menemukan level terbesar mungkin tidak terlalu sulit, tetapi akan membuat jawaban ini terlalu lama. Ini semakin lama karena itu).
Pertama, mari kita bebaskan, jika kita sudah menggunakannya sebagai integer. Kami tidak dapat mengonversi saya ke daftar, kami harus membuatnya seperti itu.
:unlet! i
Selanjutnya, mari atur i menjadi daftar yang berisi jumlah level. Anda menunjukkan 2 pada pertanyaan Anda, tetapi mari asumsikan 10 untuk bersenang-senang. Karena pengindeksan daftar didasarkan pada 0, dan saya tidak ingin repot mengoreksi untuk 1 berdasarkan daftar Anda, kami hanya akan membuat elemen yang cukup (11) dan tidak pernah menggunakan indeks 0.
:let j = 0
:let i = []
:while j < 11 | let i += [1] | let j += 1 | endwhile
Selanjutnya, kita perlu cara untuk mendapatkan nomor level. Untungnya, pengganti juga tersedia sebagai fungsi, jadi kami akan memberikannya baris kami dan mengekstrak nomor levelsubstitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")
Karena saya sekarang adalah daftar 11 1
s (setiap indeks adalah penghitung untuk level kami), sekarang kami dapat menyesuaikan salah satu contoh di atas untuk menggunakan hasil dari substitusi ini:
Melalui perintah pengganti:
:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | s/^/\=printf("%02d ", i[ind])/ | let i[ind] += 1
Melalui perintah normal:
:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | execute "normal! I" . printf("%02d ", i[ind]) | let i[ind] += 1
Input contoh:
Level 1: stuff
Level 1: Stuff
Some text
Level 3: Other
Level 1: Meh
Level 2: More
Contoh output:
01 Level 1: stuff
02 Level 1: Stuff
Some text
01 Level 3: Other
03 Level 1: Meh
01 Level 2: More