how do I search/substitute in every other line. :s/pattern1/pattern2{2}/g
file looks like
1 pattern1 text 2 pattern1 text 3 pattern1 text 4 pattern1 text
Output file should look like 1 pattern1 text 2 pattern2 text 3 pattern1 text 4 pattern2 text
how do I search/substitute in every other line. :s/pattern1/pattern2{2}/g
file looks like
1 pattern1 text 2 pattern1 text 3 pattern1 text 4 pattern1 text
Output file should look like 1 pattern1 text 2 pattern2 text 3 pattern1 text 4 pattern2 text
First thing I thought of is to just inject a conditional in a :global command. Something like this...
:g/./ if getcurpos()[1] % 2 == 0 | s/foo/bar/g | endif
The "global" command :g/./ will stop at every line that has at least one character and run the following command.
getcurpos() returns a list where the second element is the current line number. We do a modulo operation on that number and if the result is 0 we know we're on an even numbered line. In that case we do the substitution.
If you want this to substitute on odd numbered lines instead change the == to !=.
Update: @D.BenKnoble identified an optimization:
:g/foo/ if getcurpos()[1] % 2 == 0 | s//bar/g | endif
We put the pattern to be replaced in the global command. That way we don't bother processing lines that wouldn't result in a substitution. As an extra touch we can then do s//bar because leaving the pattern empty will do the substitution against the most recently used search expression.
Update 2: @ChristianBrabandt notes that getcurpos() is relatively new (v7.4.313) and offers a legacy function for fetching the current line number for those with earlier versions of Vim: replace getcurpos()[1] with line('.').
Here is an alternative. Let Vim run a :s command only on those specific lines:
for i in range(2, line('$'),2)| :exe i.'s/pattern1/pattern2/g'|endfor
This creates a loop, and iterating over each line and for each even line number executes a :<nr>s/pattern1/pattern2/g command, replacing pattern1 by pattern2. If you have pattern1 in your search register already, you can even further shorten it to for i in range(2, line('$'),2)| :exe i.'s//pattern2/g'|endfor
:100,$ g/foo/ if ....
– B Layer
Nov 03 '20 at 00:32
.with pattern and then leave it out ins//barif its every other line containing the pattern. – D. Ben Knoble Aug 11 '18 at 00:41:g/pattern1/ if line('.')% 2 == 0 | s//bar/ | endifShould also work with older Vims. – Christian Brabandt Aug 11 '18 at 06:58getcurpos()was added? – B Layer Aug 14 '18 at 03:17getcurpos()– Christian Brabandt Aug 14 '18 at 05:47:g/$/ if getcurpos()[1] % 2 != 0 | s//^I/g | endif... and then replace the delimiter::%s/^I\n/^I/g– musashiXXX Feb 15 '22 at 22:15