6

Let's say I have the following line of code:

something:somethingElse:anotherThing:woahYetAnotherThing

And I want to replace each : with a ; except the first one, such that the line looks like this:

something:somethingElse;anotherThing;woahYetAnotherThing

Is there a way to do this with the :[range]s/[search]/[replace]/[options] command without using the c option to confirm each replace operation?

As far as I can tell, the smallest range that s acts on is a single line. If this is true, then what is the fastest way to do the above task?

Will
  • 4,241
  • 4
  • 39
  • 48

4 Answers4

6

I'm fairly new to vim myself; I think you're right about range being lines-only (not 100% certain), but for this specific example you might try replacing all of the instances with a global flag, and then putting back the first one by omitting the global -- something like :s/:/;/g|s/;/:/.

Note: if the line contains a ; before the first : then this will not work.

AlliedEnvy
  • 376
  • 1
  • 5
2

Here is how you could use a single keystroke to do what you want (by mapping capital Q):

map Q :s/:/;/g\|:s/;/:<Enter>j

Every time you press Q the current line will be modified and the cursor will move to the next line.

In other words, you could just keep hitting Q multiple times to edit each successive line.

Explanation:

This will operate globally on the current line:

:s/:/;/g

This will switch the first semi-colon back to a colon:

:s/;/:

The answer by @AlliedEnvy combines these into one statement.

My map command assigns @AlliedEnvy's answer to the capital Q character.


Another approach (what I would probably do if I only had to do this once):

f:;r;;.

Then you can repeatedly press ;. until you reach the end of the line.

(Your choice to replace a semi-colon makes this somewhat comfusing)

Explanation:

  • f: - go to the first colon
  • ; - go to the next colon (repeat in-line search)
  • r; - replace the current character with a semi-colon
  • ; - repeat the last in-line search (again)
  • . - repeat the last command (replace current character with a semi-colon)

Long story short:

  • fx - moves to the next occurrence of x on the current line
  • ; repeats the last inline search
jahroy
  • 22,322
  • 9
  • 59
  • 108
2

Here you go...

:%s/\(:.*\):/\1;/|&|&|&|&

This is a simple regex substitute that takes care of one single not-the-first :.

The & command repeats the last substitute.

The | syntax separates multiple commands on one line. So, each substitute is repeated as many times as there are |& things.

DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
2

While the other answers work well for this particular case, here's a more general solution:

Create a visual selection starting from the second element to the end of the line. Then, limit the substitution to the visual area by including \%V:

:'<,'>s/\%V:/;/g

Alternatively, you can use the vis.vim plugin

:'<,'>B s/:/;/g
Ingo Karkat
  • 167,457
  • 16
  • 250
  • 324