Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

vi: :s how to replace only the second occurence on a line?

Tags:

regex

vi

:s/u/X/2 - this replaces the first u to X on the current and next line...

or to replace the second character on a line with X???? IDK.

or perhaps its something other than :s?

I suspect I have to use grouping of some kind (\2?) but I don't know to write that.

I heard that sed and :s option in sed are alike, and on a help page for sed I found:

3.1.3. Substitution switches:

Standard versions of sed support 4 main flags or switches which may be added to
the end of an "s///" command. They are:

   N      - Replace the Nth match of the pattern on the LHS, where
            N is an integer between 1 and 512. If N is omitted,
            the default is to replace the first match only.
   g      - Global replace of all matches to the pattern.
   p      - Print the results to stdout, even if -n switch is used.
   w file - Write the pattern space to 'file' if a replacement was
            done. If the file already exists when the script is
            executed, it is overwritten. During script execution,
            w appends to the file for each match.

http://sed.sourceforge.net/sedfaq3.html#s3.1.3

so: :r! sed 's/u/X/2' would work, although I think there is a specifically vi way of doing this?

IDK if its relevant but I'm using the tcsh shell.

also, :version: Version 1.79 (10/23/96) The CSRG, University of California, Berkeley.

like image 604
jason dancks Avatar asked Apr 01 '14 02:04

jason dancks


People also ask

How do I change a whole line in Vim?

If you want to select the entire line in a file, press V. Now when you press k or j to go up and down, vim will select the entire line above and below your cursor.


1 Answers

This is brittle, but may be enough to do what you want. This switch command with regex:

:%s/first\(.\{-}\)first/first\1second/g

converts this:

first and first then first again
first and first then first again
first and first then first again
first and first then first again

to this:

first and second then first again
first and second then first again
first and second then first again
first and second then first again

The regexp looks for the first "first", followed by a match of any characters using pattern .\{-}, which is the non-greedy version of .* (type :help non-greedy in vim for more info.) This non-greedy match is followed with the second "first".

The characters between the first and second "first" are captured by surrounding the .\{-} with parenthesis, which, with escaping results in \(.\{-}\), then that captured group is dereferenced with the \1 (1 means first captured group) in the replacement.

like image 139
lreeder Avatar answered Oct 12 '22 15:10

lreeder