5

The root of my question is about a difference between the way Vim processes multiple substitutions and they way other editors (Sublime, for example) do it.

I have this file:

thing1
thing2
thing3
thing4
thing5

And I want to perform this substitution:

:%s/\v^(.*)$\n?/'\1',/

In Sublime, performing a "Replace All" with that regex & replacement results in what I intended:

'thing1','thing2','thing3','thing4','thing5',

In Vim, though, I get this:

'thing1',thing2
'thing3',thing4
'thing5',

Adding a c flag seems to explain this behavior:

Incremental substitution

Vim seems to be processing each substitution one at a time, which then causes the next line not to match, because it's no longer at the start of the line.

Removing ^ from the regex makes it work as expected, but is there another way? Is there any way to make Vim's substitution behave more like other editors' -- i.e. identifying all matches, then replacing them all regardless of how they're changed by earlier substitutions?

6

What is going on? Why does Vim behave this way vs Sublime Text?

I do not know Vim's internals (open source) and I do not know Sublime Text's internals (closed source) either, but we can guess what is going on here.

From your example we see that vim does substitutions iteratively. Therefore, the ^ does not match for next piece of text after a single substitution. Sublime Text on the other hand seems to do all the matching up front and then does all the substitutions. It is a subtle but slight difference. Normally it doesn't matter.

So the next question is why does Vim behave this way? My guess this behavior is an optimization. My proof would be creating a file with the following text:

aaaaaab
aaaaaacaaaaaab
aaaaaadaaaaaab
aaaaaab

Now duplicate those lines a large amount like 10,000 times (total of 40,000 lines). Now do the following substitution:

:%s/a*b/foo/g

What happens?

Vim handles it like a champ. It is fast!. Although a little slower with set regexengine=1.

Sublime Text stalls for quite some time then finally does the replacement. If you increase the number of a's then eventually you can make Sublime Text stall by just typing in the "Find What" portion of the text, not even getting to the "Replace With" field yet?!

Note: I tested this with Sublime Text 2 and Vim 8

Can Vim work like Sublime Text?

I do not know of any native way to change this behavior. You may be able to create your own version of :substitute which does the initial matching first and then the substitution.

Conclusion

Both Vim and Sublime Text use different regex engines. I think it is perfectly reasonable to expect them to behave slightly differently when it comes to substitutions as well.

If you want to see your substitutions as you type I recommend you use traces.vim or Neovim's 'inccommand'.

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.