Using Vim's Very Magic Regex to Format Code
Do you ever find yourself typing the same string formats in code on repeat? Vim’s regex search and replace is a powerful tool for automating this problem. It doesn’t come up everyday, but frequently enough that I forget the next time I need it. With vim’s regex, we can turn this:
one
two
three
into this:
("ONE", "One"),
("TWO", "Two"),
("THREE", "Three"),
1. Let’s Build A Regex
1.1 Duplicating Words
First we need to duplicate our words by:
- pressing
:
- typing
%s/\w\+/\0 \0/
- hitting enter
This will result turn our original input into:
one one
two two
three three
%s
the range of the substitute command, in our case the entire file.\w
matches any alphanumeric character or underscore[a-zA-Z0-9_]
\+
greedy match preceding character 1 or more times\0 \0
will replace with the previous matching pattern twice with a space between
1.2 Upper/Lower Casing
Alright, now let’s look into setting the casing.
We want the first word uppercase, capitalize the first character of the second word, then all lower case.
Vim’s \u
, \U
, and \L
will work nicely.
\u
uppercases the next character.\U
uppercases the following characters\l
and\L
are the same for lowercase
Using our original input, we can update our regex to %s/\w\+/\U\0\L \u\0/
:
ONE One
TWO Two
THREE Three
1.3 Special Characters
The last thing we need is to add some (
, "
, and ,
to the text.
But, (
and ,
have special meaning in regex.
That means we need to escape them by adding a backslash (\(
and \,
for example)
Hold on, the regex is about to get messy: %s/\w\+/\("\U\0\L"\, "\u\0"\)\,/
:
("ONE", "One"),
("TWO", "Two"),
("THREE", "Three"),
Success! We have our regex!
2. Making Vim Regex Magical
Remembering that regex never comes easy for me.
Fortunately, vim comes with a feature called “very magic” to help.
It assumes every character is a special character, meaning you don’t need to add the backslash.
You enable this by adding \v
into your regex.
This simplifies our last regex to: %s/\v(\w+)/("\U\0\L", "\u\0"),/
Which makes parsing a bit easier.
3. Multiple Words
What if we’re not duplicating words? What if we have different values we want to use? For example:
one red
two blue
three green
Vim can handle that too.
In the beginning we used \0
to mean the single matched word.
You can search for multiple words and use \1
and \2
to refer to them.
If we want to convert to a similar format we could run %s/\v(\w+) (\w+)/("\1", "\2"),/
:
("0", "red"),
("1", "green"),
("2", "blue"),
4. Piping To Vim
Don’t quote me on the practical value of this, but it’s fun to know. You can use vim’s regex to replace text in bash pipes.
$ echo "one\ntwo\nthree" | vim -es '+%s/\v(\w+)/("\U\0\L = "\u\0"),/' '+%print' '+:q!' /dev/stdin
("ONE = "One"),
("TWO = "Two"),
("THREE = "Three"),
I’d probably use sed
before reaching for vim.
5. Conclusion
Vim’s regex search and replace is a powerful tool in your belt.
You can make yaml options %s/\v(\w+)/\0: \0/
:
one: one
two: two
three: three
Python dict entries %s/\v(\w+)/"\0": "\0",/
:
"one": "one",
"two": "two",
"three": "three",
Or any other format you can think of. It’s language agnostic and useful in all kinds of situations. Happy Regexing!