Vim: s ganti N <g kejadian pertama pada suatu garis


13

Dalam vim, saya kadang-kadang memiliki kesempatan untuk mengganti beberapa kejadian pertama pertandingan pada satu baris, tetapi tidak semua orang seperti gitu. misalnya:

a a a a a

untuk

b b b a a

Saya tahu saya bisa menggunakan :s/a/b/[enter]:[up][enter]:[up][enter], tapi itu cukup membosankan di tiga pengulangan, saya memiliki garis dengan berpotensi pengganti 10+.
Saya sudah mencoba:

  • :s/a/b/3g: vim mengeluh tentang karakter yang tertinggal.
  • :s/a/b/3: mengubah kemunculan pertama pada ini dan dua baris berikut.
  • 3:s/a/b: sama seperti sebelumnya.
  • :s/a/b/g3: mengubah semua kemunculan pada ini dan dua baris berikutnya.
  • :3s/a/b: mengubah kejadian pertama pada baris 3.
  • :/a/,3/a/s/a/b: mengubah kemunculan pertama pada setiap baris antara baris berikutnya adan ketiga yang berisi adalam file (diminta untuk membalikkan jika perlu).
  • :/a/,/\([^a]*a\)\{3\}/s/a/b/: mengubah kemunculan pertama pada setiap baris antara ini dan berikutnya dengan 3 adetik di atasnya (dan ini tidak akan mudah diperluas ke pencarian multi-karakter).

Dan berbagai pola pengalamatan lainnya, tidak ada yang berhasil. Saya harus mengatakan, saya telah belajar cukup banyak tentang :sperintah yang mencoba menemukan jawaban untuk masalah ini, tetapi saya masih belum menyelesaikannya.

Adakah yang tahu bagaimana melakukan ini?

(poin bonus untuk rentang tertentu, misalnya kejadian kedua hingga keempat)


2
Saya cukup yakin Anda tidak dapat melakukannya di vim, tetapi untuk membuatnya tidak terlalu membosankan, apakah Anda tahu tentang "n" dan "." dalam mode visual? Artinya, Anda menggunakan / pattern / untuk menemukan hal untuk diubah, mengubahnya menggunakan "cw" atau apa pun, lalu gunakan "n" (hanya n, tanpa tanda kutip) untuk menemukan pola berikutnya dan tekan "." (cukup titik, tanpa tanda kutip) untuk melakukan edit terakhir.
Bruce Ediger

@BruceEdiger saya tahu tentang ndan ., meskipun saya tidak berpikir untuk menggunakannya di sini. Tentu saja perbaikan, terima kasih.
Kevin

s/a/=something/harus melakukan trik ( :help sub-replace-=). Saya tidak cukup lancar dalam Vim untuk menulis somethinglangsung dari kelelawar.
Gilles 'SO- stop being evil'

Catatan: :[up][enter]dapat diganti dengan &, yang masih tidak ideal tetapi setidaknya kurang menyakitkan.
Kowh

Jawaban:


10

Membangun :s/pattern/replacement/gc ide dari Samus_ (yang tampaknya menjadi cara paling sederhana untuk memastikan operasi yang benar ketika pola terkandung dalam string pengganti), untuk mengganti kejadian 2 hingga 4 pada satu baris:

:call feedkeys("nyyyq") | s/pat/string/gc

feedkeys()adalah fungsi yang memasukkan string input ke antrian input keyboard. Intinya adalah melakukan penghitungan dimuka sehingga Anda tidak perlu khawatir kehilangan hitungan atau terganggu.

Untuk kasus yang lebih umum, untuk mengganti Mth hingga Nth kejadian pada satu baris untuk N lebih besar atau sama dengan M yang sangat besar :

:call feedkeys(repeat("n", M-1) . repeat("y", N-M+1) . "q") | s/pat/string/gc

Ganti M dan N dengan nilai yang Anda inginkan (Anda bahkan dapat membiarkan vimmelakukan aritmatika mental sepele jika Anda tidak ingin melakukannya sendiri). Perhatikan bahwa .adalah operator penggabungan string VimL. Jelas ini hanya menghemat penekanan tombol untuk M besar . Jika Anda sering menggunakan fungsi ini, mungkin akan menghemat waktu Anda untuk memasukkan perintah atau fungsi khusus semacam itu di atas, karena cukup sedikit untuk diketik.


Hmm. Saya suka yang ini. Saya harus bisa menulis fungsi untuk itu juga.
Kevin

8

Untuk pertanyaan pertama yang akan saya lakukan:

:s/a/b
&&

Yang kedua lebih rumit, saya tidak tahu cara melakukannya secara otomatis tetapi Anda dapat membuat vim meminta Anda pada setiap pertandingan seperti ini:

:s/a/b/gc

Kemudian Anda menjawab "tidak" pada n yang pertama cocok dan "ya" kepada yang lain.


Hmm, saya lupa c, itu mungkin solusi terbaik yang diusulkan. Saya masih harus menghitung, tapi saya pikir itu adalah opsi pertama yang akan bekerja dengan penggantian yang berisi string pencarian.
Kevin

6
a a a a a
a a a a a
a a a a a
a a a a a
a a a a a
a a a a a
a a a a a

:3,6g/^/let i=0 | while i<3 | s/a/b/ | let i+=1 | endwhile

a a a a a
a a a a a
b b b a a
b b b a a
b b b a a
b b b a a
a a a a a

1
Ini bagus, tetapi masih mengalami masalah yang Gilles tunjukkan (pada pos lain, yang karena tampaknya telah dihapus), bahwa itu hanya berfungsi jika penggantian tidak mengandung pola. Meskipun saya suka ide skrip.
Kevin

Suatu hal yang indah!
Uskup

1

Saya pikir ini mungkin berhasil, ganti dulu, lalu ulangi 2 kali:

:s/a/b/
2@:
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.