vim regexp magic

Input, this one big liner:

function UnitUserSettingsSave( tInteger $dobd, tInteger $dobm, tInteger $doby, tText $gender, tInteger $place, tInteger $education, tInteger $school, tInteger $mood, tText $sex, tText $religion, tText $politics, tText $slogan, tText $aboutme, tText $favquote, tText $haircolor, tText $eyecolor, tInteger $height, tInteger $weight, tText $smoker, tText $drinker, tText $email, tText $msn, tText $gtalk, tText $skype, tText $yahoo, tText $web, tText $oldpassword, tText $newpassword, tText $emailprofilecomment, tText $notifyprofilecomment, tText $emailphotocomment, tText $notifyphotocomment, tText $emailpollcomment, tText $notifypollcomment, tText $emailjournalcomment, tText $notifyjournalcomment, tText $emailreply, tText $notifyreply, tText $emailfriendaddition, tText $notifyfriendaddition, tText $emailtagcreation, tText $notifytagcreation, tText $emailfavourite, tText $notifyfavourite ) {

Output, this beautifully spaced multiliner:

function UnitUserSettingsSave( tInteger $dobd, tInteger $dobm,
          tInteger $doby, tText $gender,
          tInteger $place, tInteger $education,
          tInteger $school, tInteger $mood,
          tText $sex, tText $religion,
          tText $politics, tText $slogan,
          tText $aboutme, tText $favquote,
          tText $haircolor, tText $eyecolor,
          tInteger $height, tInteger $weight,
          tText $smoker, tText $drinker,
          tText $email, tText $msn,
          tText $gtalk, tText $skype,
          tText $yahoo, tText $web,
          tText $oldpassword, tText $newpassword,
          tText $emailprofilecomment, tText $notifyprofilecomment,
          tText $emailphotocomment, tText $notifyphotocomment,
          tText $emailpollcomment, tText $notifypollcomment,
          tText $emailjournalcomment, tText $notifyjournalcomment,
          tText $emailreply, tText $notifyreply,
          tText $emailfriendaddition, tText $notifyfriendaddition,
          tText $emailtagcreation, tText $notifytagcreation,
          tText $emailfavourite, tText $notifyfavourite ) {

How? With one command, in vim:

:s/\(.\{-1,}\),\(.\{-1,}\),/\1,\2,\r        /ig

What does it do?

First off, :s/needle/replacement/g searches the current line for regular expression needle and replaces it with expression replacement. The current line is being searched because we didn’t specify a range before the “s”. “s” is the extended command that we’re running, which stands for “search and replace”. The “g” modifier after the final slash stands for “global”, meaning it should feel free to replace several occurrences in the same line, not just the first.

Now, for the needle expression. It can be essentially split into two parts:
1) \(.\{-1,}\),
2) \(.\{-1,}\),

These two expressions match exactly the same thing. They match anything they want, denoted with a dot, followed by a comma (the one that you see at the end of each expression). The “anything they want part” denoted with a single dot is just one character, so we’re modifying it to be able to match more than just one character (as many as it needs to satisfy the comma at the end) by adding the lazy quantifier \{-1,} after the dot.

The expression .\{-1,} means: match as many of any characters as you need to match the whole expression. In reality, because this is a lazy quantifier, it matches as less characters as possible providing it can find a comma right afterwards (but not the comma itself).

So both expressions tied together match anything followed by a comma followed by anything followed by a comma. Translation? They match two of the arguments of those provided in the function argument list.

The parentheses around each of them denoted \( and \) capture what is within, to be used in the replacement string. Our replacement string is simply “\1,\2,\r “. It will replace \1 with the first parenthesized match, then add a comma, then replace the \2 with the second parenthesized match, then add yet another comma. Finally it will add a new line (\r) and some whitespace.

Repeating this pattern with the “global” modifier applies the regular expression several times on the line, yielding to new lines being added after every second argument.

Leave a Reply