11

I have a file with a line that looks like this:

foofoo.xy.barbar

I want to change the xy to gh. I tried to do 2r -> gh, but obviously that didn't work, as it replaced the xy with gg and then moved my cursor one spot to the left.

Is there a way to do this without entering insert mode, or without using a lot more keystrokes (e.g. :s/xy/gh/)?

  • 2
    R enters Replace Mode. :help replace-mode for more information. – alxndr Feb 12 '15 at 0:55
  • I tried vt.rgh. But the result was the same as yours except for the cursor position. – Gonçalo Ribeiro Feb 12 '15 at 1:17
  • 2
    Why don't you want to enter insert mode? Something like cwgh<esc> would work fine. – Doorknob Feb 12 '15 at 2:07
  • 1
    @durron597 I'm not sure if minimize-keystrokes is a good tag, it's usually not really what the question is about, as such. (I rejected your proposed edits) ... Perhaps you should discuss at meta? – Martin Tournoij Feb 12 '15 at 13:47
19

If the new text is the same length as the old text, Vim's replace mode is an option. From normal mode, R (that's a capital "r") brings you into replace mode. This is similar to "overwrite" in some other text editors: instead of inserting new characters like in insert mode, typing will replace the character under the cursor, and then advance to the next cursor. (Think of it like the lower-case r, but for more than just a single character at a time.) Find the documentation for replace mode with :help replace-mode.

In your case: with the cursor between the . and the x, get in to replace mode by pressing R. Now when you type g it replaces the "x" and moves to the next character, so you can type h to replace the "y". Your edit is done now, so Escape to return to to normal mode.

(This works when your replacement text is the same length as the old text, but if your replacement is longer or shorter, c might be all you need: it will replace1 the text within a movement, with the text you then type. There are many ways to do use c, for example: with the cursor between the . and x, ct.ABCEscape says to change the text (up 'til the next .) with "ABC".)


1 It'll yank the text in the movement into the unnamed/" register and then switch into insert mode, so that you can type something to replace it, and then Escape back to normal mode.

  • 2
    This works for this case. What if you wanted to replace those 2 chars by say 3 chars? – Gonçalo Ribeiro Feb 12 '15 at 1:19
  • 1
    Good question; amended to include a way to handle different length text. – alxndr Feb 12 '15 at 1:22
  • Yeah, I know that way. But that way you enter Insert mode and I was curious to see if there was a way not to use Insert mode in that case. Not that I think it very useful (and yet I could be wrong). – Gonçalo Ribeiro Feb 12 '15 at 1:26
  • Prefix with a numeral n to replace up to the n-th occurence of the target character. This is useful for replacing parts of labels with the format w_x_y_z and a-b-c-d. Use f instead of t to remove the limiting character as well. – pkfm yesterday
5

There are a couple ways you could do this, but the simplest I can think of is:

TL;DR

fxcw<REPLACEMENT TEXT>

Explanation

  • fx jumps you to the x (see help *f*)
  • cw says to change the word (see :h *c*, :help *w*, and :help cw for more information), removing the "xy" text and entering insert mode, letting you put whatever you want right there.
  • < REPLACEMENT TEXT > is whatever you want to replace it with - "gh" in your example.

One advantage of this approach is that it uses very commonly used text manipulation & navigation commands. Another is that "xy" could be of any length, and this would still work.

The cw works because your text object is surrounded by periods (.), which act as a boundary to the word.

If your cursor is already on the "y" character (or any character in the text to be replaced), you could use ciw<REPLACEMENT TEXT>. This tells vim to change the word you're in, even if you're not at the beginning of it. See :help text-objects for more information on ciw and text objects in general.

  • won't this place him in insert mode? – elyashiv Feb 12 '15 at 12:00
  • 1
    Ah - didn't catch that part of his question. In that case, yes - R is the most appropriate solution. – Cody Poll Feb 12 '15 at 15:53
3

Replace mode:

Rgh<Esc>

is the most obvious solution if the replacement is the same length as the original but you could also do:

2sgh<Esc>

or:

cegh<Esc>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.