29

Sometimes I use :s with a complicated regexp which may or may not be correct, or I'm not sure if I want to replace all matches.

Is there any way I can tell Vim to confirm every match it finds before it actually replaces the text?

D. Ben Knoble
  • 26,070
  • 3
  • 29
  • 65
Martin Tournoij
  • 62,054
  • 25
  • 192
  • 271

5 Answers5

35

Yes! Use the c flag for :substitute. From :help substitute:

[c]     Confirm each substitution.  Vim highlights the matching string (with
        hl-IncSearch).  You can type:                           :s_c
            'y'     to substitute this match
            'l'     to substitute this match and then quit ("last")
            'n'     to skip this match
            <Esc>   to quit substituting
            'a'     to substitute this and all remaining matches {not in Vi}
            'q'     to quit substituting {not in Vi}
            CTRL-E  to scroll the screen up {not in Vi, not available when
                        compiled without the +insert_expand feature}
            CTRL-Y  to scroll the screen down {not in Vi, not available when
                        compiled without the +insert_expand feature}

Example usage is simple as pie:

%s/old/new/gc

This is very useful, but didn't know about this until 2 weeks ago :-) And it's even available in ol' vi :-)

Bonus tip: You may also want to use :set nowrapscan; this prevents Vim from wrapping to top when it hits the bottom. I've found this to be especially useful when using the c flag.

Martin Tournoij
  • 62,054
  • 25
  • 192
  • 271
  • I would also add that if you want to replace all instances of old in the same line (not just the first occurrence) you should add g at the end of the command so in total you will have %s/old/new/gc – e271p314 Apr 19 '20 at 16:53
  • Oh, yeah; I have set gdefault so I tend to forgot to add it in examples @e271p314 – Martin Tournoij Apr 19 '20 at 18:05
23

In addition to what Carpetsmoker said:

The &incsearch (set incsearch) setting in Vim is really useful. You can use it together with a useful and little known trick.

The trick is to try out your complex regex by just using the / or ? command. Vim will use the &incsearch setting to show matches interactively. Once you're happy with the regex, you can use :%s//replacement to have vim use the previous search.

Notice how the part in // is blank (that's where you put the text to search). If you leave it blank, you are telling Vim to use the previous search regex. With this, you can type out a complex regex with / and have all the benefits of set incsearch, and then use the %s//replacement command to actually execute the search and replace.

If you want something similar to incsearch for :s commands, check out vim-over, but I just prefer using the native Vim way.

akshay
  • 6,497
  • 37
  • 43
  • I used to use a variant of this: Just use :%s/pattern/replace/ and then press u for undo, you can see the parts that Vim changed if you have hlsearch enabled. And you can replace this text again with ^R. – Martin Tournoij Feb 05 '15 at 15:35
14

My favorite interactive substitution is to search using / and go through the matches using n.

Then select match using gn and then s to substitute the text with whatever I like.

And repeat by moving to next match and pressing .

  • This is a very nice trick, because it is: (1) interactive, (2) you can go previous match if you accidentally skipped it (something that you cannot do using :s/old/new/gc). – Ayrat Sep 12 '18 at 08:54
5

In Neovim there also is the 'inccommand' option which lets you preview the result of the :s command while you type it.

Lucas
  • 1,629
  • 10
  • 21
3

For the benefit of everyone, incsearch was updated in vim8 to also show preview as you type the pattern

Dhruva Sagar
  • 5,510
  • 2
  • 22
  • 17