DEV Community

Sérgio Araújo
Sérgio Araújo

Posted on • Edited on

Vim: More submatch tricks (and regexes)

How to search and replace in Vim with submatch values

I normally learn a lot on stackoverflow and this comes from it once more

Let's say you have to turn this:

<form>
    <input id="firstname" value="" />
    <input id="lastname" value="" />
    <input id="email" value="" />
</form>
Enter fullscreen mode Exit fullscreen mode

into this:

<form>
    <input id="firstname" name="firstname" value="" />
    <input id="lastname" name="lastname" value="" />
    <input id="email" name="email" value="" />
</form>
Enter fullscreen mode Exit fullscreen mode

To match only the value after the first equal sign

/id=\v\zs(".{-}")
Enter fullscreen mode Exit fullscreen mode

In our above search we have some tricks, the first one is that we only start the very magic after the equal sign, because on vim magic search the equal needs scape. The second trick is using a non-greedy search, for more on this try :help non-greedy. The third trick is using our beloved \zs an unique vim regex feature that says: Beloved vim, use in our substitution only what comes after this point. The oposite is: \ze. For more try: :h \zs. The final trick is using the amper sign & that represents the whole matched pattern.

To apply changes only over a specific paragraph use:

vip  ............... visual inner paragraph
Enter fullscreen mode Exit fullscreen mode

And the final command becomes

:'<,'>s//& name=&
Enter fullscreen mode Exit fullscreen mode

Notice the double slashes another trick that says to vim: Beloved vim: Don't bother copying the last search to my command line command, just use it as if I have typed it. This trick allows me to separate my search from my substitution command, creating a more concise and easy to read/learn command.

Translating part of a line

some_variable = True #循迹红外传
Enter fullscreen mode Exit fullscreen mode

So you catch the commenting part with this regex:

    /\v([^#]*&[^"']|^)\zs#.+\ze
Enter fullscreen mode Exit fullscreen mode

And you happen to have the program trans installed on your system. You can translate the Chinese part with:

:.s/\v([^#]*&[^"']|^)\zs#.+\ze/\=system('trans -b :en "'. submatch(0) . '"')
Enter fullscreen mode Exit fullscreen mode

It is even easier to break down the solution into two pieces:

1 - Search
2 - Substitution

   /\v([^#]*&[^"']|^)\zs#.+\ze
   :.s//\=system('trans -b :en "'. submatch(0) . '"')
Enter fullscreen mode Exit fullscreen mode

More reading

I have written another similar post with more stuff, see it here.

Top comments (0)