loading...

Vim: More submatch tricks (and regexes)

voyeg3r profile image Sérgio Luiz Araújo Silva Updated on ・2 min read

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>

into this:

<form>
    <input id="firstname" name="firstname" value="" />
    <input id="lastname" name="lastname" value="" />
    <input id="email" name="email" value="" />
</form>

To match only the value after the first equal sign

/id=\v\zs(".{-}")

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

And the final command becomes

:'<,'>s//& name=&

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 #循迹红外传

So you catch the commenting part with this regex:

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

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) . '"')

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) . '"')

More reading

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

Posted on by:

voyeg3r profile

Sérgio Luiz Araújo Silva

@voyeg3r

I am a Free Software enthusiast and a (neo)?vim addicted, I also like shell script, sed, awk, and as you can see I love Regular Expressions.

Discussion

markdown guide