We know how to replace a pattern, but we can do more. Substitute is more powerful than it seems. Break it down.
Replace with match
Sometimes we want to replace a pattern, but we want to keep some parts of it.
For example we have a list of machine names, all of them are constructed in this
form: {name}-{id}-{location}
, and we want to rename them to follow the new
naming logic: {location}-{name}-{id}
.
titan-13-eu-west
arachnitect-08-eu-west
titan-43-us-east
ventrexia-77-us-west
tryvuulia-03-ap-south
tryvuulia-03-ap-northeast
rugaro-13-eu-central
We can match them with [a-z]\+-[0-9]\{2\}-[a-z-]\+
, yes it’s a bit of regular
expression magic, but a quick summary:
Now we can group them with ()
, so we can reference back to the sub-match:
\([a-z]\+\)-\([0-9]\{2\}\)-\([a-z-]\+\)
. Now we have a regular expression with
sub-match groups.
There is an option to enable very-magic mode. If we want to use special
characters like (){}+
, without spamming the patter with \ characters, we can
enable magic using \v
. With this the pattern we used above can be simplified
to: \v([a-z]+)-([0-9]{2})-([a-z-]+)
. It does the same thing, but without a
lot of extra \ characters.
In the replacement part of the substitution, we can refer to sub-match groups
with \1
, \2
, etc.
We have 3 groups:
\1
: Name.\2
: ID.\3
: Location.
It’s time to rename out servers:
:%s/\v([a-z]+)-([0-9]{2})-([a-z-]+)/\3-\1-\2/g
.
After this we get what we wanted, all servers are renamed to the new naming
format.
eu-west-titan-13
eu-west-arachnitect-08
us-east-titan-43
us-west-ventrexia-77
ap-south-tryvuulia-03
ap-northeast-tryvuulia-03
eu-central-rugaro-13
Upper case, lower case
We can do even more magic with substitution, for example we can generate a “human readable” name for our servers in a report where the name should start with an upper case letter.
Similar to \{number}
, we can use markers to change the next or the following
letters.
\u
: Next character made upper case.\U
: Following characters made upper case, until\E
\l
: Next character made lower case.\L
: Following characters made lower case, until\E
With this, we can generate a list with a much easier to read names. We start with the new naming format:
eu-west-titan-13
eu-west-arachnitect-08
us-east-titan-43
us-west-ventrexia-77
ap-south-tryvuulia-03
ap-northeast-tryvuulia-03
eu-central-rugaro-13
What we want is a nice format like: Tryvuulia #03 (ap-northeast)
. With little
changes we can use the same regular expression, we as we flipped groups we have
this: \v([a-z-]+)-([a-z]+)-([0-9]{2})
. As we want to change only the first
letter of the name to be upper case, we can use \u
, and change the ordering
again:
:% s/\v([a-z-]+)-([a-z]+)-([0-9]{2})/\u\2 #\3 (\1)/
. And finally we got our
user friendly list:
Titan #13 (eu-west)
Arachnitect #08 (eu-west)
Titan #43 (us-east)
Ventrexia #77 (us-west)
Tryvuulia #03 (ap-south)
Tryvuulia #03 (ap-northeast)
Rugaro #13 (eu-central)
We know from day 7 how to sort this, so let’s do it:
Arachnitect #08 (eu-west)
Rugaro #13 (eu-central)
Titan #13 (eu-west)
Titan #43 (us-east)
Tryvuulia #03 (ap-northeast)
Tryvuulia #03 (ap-south)
Ventrexia #77 (us-west)