Cari dan ganti di vim di baris tertentu

95

Saya bisa menggunakan

:5,12s/foo/bar/g

untuk mencari foodan menggantinya di barantara baris 5 dan 12. Bagaimana saya bisa melakukannya hanya di baris 5 dan 12 (dan bukan di baris di antaranya)?

pfnuesel.dll
sumber

Jawaban:

76

Vim memiliki atom ekspresi reguler khusus yang cocok dalam baris, kolom, dll. Tertentu; Anda dapat menggunakannya (mungkin sebagai tambahan dari jangkauan) untuk membatasi kecocokan:

:5,12s/\(\%5l\|\%12l\)foo/bar/g

Lihat :help /\%l

Ingo Karkat
sumber
8
Cara yang lebih rumit dari yang saya harapkan tetapi menjawab pertanyaan saya dengan sempurna. Terima kasih!
pfnuesel
56

Anda dapat melakukan substitusi pada baris 5 dan mengulanginya dengan sedikit usaha pada baris 12:

:5s/foo/bar
:12&

Seperti yang ditunjukkan oleh Ingo, :&lupakan benderamu. Karena Anda menggunakan /g, perintah yang benar adalah :&&:

:5s/foo/bar/g
:12&&

Lihat :help :&dan teman-teman.

romainl
sumber
10
1 untuk menempatkan obscure :&untuk digunakan. Jika ada bendera ( s/../../g), seseorang harus menggunakan :&&, meskipun ...
Ingo Karkat
10
@IngoKarkat, agar adil, menurut saya \(\%5l\|\%12l\)lebih tidak jelas daripada:&
doubleDown
13

Anda selalu bisa menambahkan a cdi akhir. Ini akan meminta konfirmasi untuk setiap pertandingan.

:5,12s/foo/bar/gc
Dekan
sumber
1
Ini bisa menjadi mimpi buruk jika ada banyak pertandingan di antara baris 5 dan 12 (perlu diingat bahwa ada gbendera dalam permainan)
doubleDown
1
@doubleDown Ini tidak dimaksudkan sebagai solusi universal (di mana ada banyak kandidat yang mungkin), tetapi dalam banyak kasus apakah Anda benar-benar hal menekan n5 atau 6 kali lebih berat daripada menambahkan \(\%5l\|\%12l\)ke pernyataan pengganti?
Dean
Saya menemukan ini berguna, saya ingin mengubah setiap baris lainnya, ini akan menjadi lebih cepat daripada yang akhirnya saya lakukan.
tiktak
9

Pertanyaan menarik. Sepertinya hanya ada pilihan rentang dan tidak ada pilihan banyak garis:

http://vim.wikia.com/wiki/Ranges

Namun, jika Anda memiliki sesuatu yang istimewa di jalur 5 dan 12, Anda dapat menggunakan :goperatornya. Jika file Anda terlihat seperti ini (angka hanya untuk referensi):

 1     line one
 2     line one
 3     line one
 4     line one
 5     enil one
 6     line one
 7     line one
 8     line one
 9     line one
10     line one
11     line one
12     enil one

Dan Anda ingin mengganti onedengan enopada baris di mana ada enilsebagai ganti line:

:g/enil/s/one/eno/
eckes
sumber
5
ini sebenarnya mengasumsikan banyak
doubleDown
1

Anda dapat menggunakan ed- editor teks berorientasi garis dengan perintah yang mirip dengan vi dan vim. Ini mungkin mendahului vi dan vim.

Dalam skrip (menggunakan dokumen di sini yang memproses input hingga penanda EndCommand) akan terlihat seperti:

ed file <<EndCommands
    5
    s/foo/bar/g
    7
    s/foo/bar/g
    wq
EndCommands

Jelas, perintah ed dapat digunakan pada baris perintah juga.

suspectus
sumber
3
Saya tidak melihat keuntungan dibandingkan vimalternatifnya.
Bernhard
1
Dan hal yang sama juga bisa dilakukan dengan Vim; nomor sebenarnya dapat diletakkan sebelum :s, tetapi masih ada duplikasi :sperintah (yang dihindari oleh solusi romainl).
Ingo Karkat
Menurut saya, pengguna mungkin ingin memilih lebih dari dua baris untuk diedit. Dalam hal ini pendekatan non-interaktif mungkin menarik - yang AFAIK tidak dapat dilakukan dengan vim.
tersangka
1
Oh, Vim dapat melakukan itu (misalnya dalam mode "Ex"), tetapi Anda benar bahwa alat lain harus lebih disukai daripada editor interaktif. Preferensi saya adalah sed, meskipun ...
Ingo Karkat