Jun 22 2012
Lookbehind / Lookahead Regex in Vim
Here’s a nifty little vim tip for you.
I recently had to switch a few variables in PHP from $varname to $somearray[‘varname’]. Since there were quite a few of these replacements to be done, I found it convenient to use vim’s search/replace regex feature. In this case, I have to use lookbehind, since the matching string is simply varname, and I’m not interested in catching the $ at the beginning. I just want the regex to match anything starting with the $, without having the $ as part of the matching string itself.
So, let’s try to replace the following line:
authenticate($key, $secret, $uri);
with this one:
authenticate($somearray['key'], $somearray['secret'], $somearray['uri']);
We’ll want to construct a lookbehind for the $, with some string in front. Then, we’ll replace it with $somearray[‘matching_string‘]. In vim, lookbehind uses the special @ symbol, rather than the perl (?<=somestring) syntax. [shell] :'<,'>s/\$\@<=[a-z]\+/$somearray['&']/g [/shell] This will do the trick. As you can see, the $, @, and + must all be escaped. The lookbehind positive search chars, @<= can be replaced with @<! if a negative search is desired. Lookahead is similar to lookbehind’s syntax, but uses @= and @! instead. The special & character in the replace string designates a matching token, which you can use to place the matching string in your replacement.
So for reference:
-
:%s/\(some\)\@<=thing/one/g
searches for all strings starting with some, then matching thing
changes thing into oneend result: something becomes someone
-
:%s/\(some\)\@<!thing/one/g
searches for all strings not starting with some, then matching thing
changes thing into oneend result: something is not changed, but everything changes to everyone
-
:%s/some\(thing\)\@=/every/g
searches for all strings ending with thing, then matching some
changes some into everyend result: something becomes everything
-
:%s/some\(thing\)\@!/every/g
searches for all strings not ending with thing, then matching some
changes some into everyend result: something is not changed, but someone becomes everyone