Not your average regex find-and-replace

December 25, 2008

I was reading through some of the Coding Horror archives, and came across this post examining Microsoft Visual Studio’s use of regular expressions in its find-and-replace dialog. Visual Studio has support for all of the usual regex constructs but throws in a lot of its own quirky constructs too. I suppose they could be useful if you learned to use them.

But this post isn’t about Visual Studio. Jeff’s post contained an intriguing link to Steve Yegge’s blog, where Steve goes over some of the new features in Emacs 22. And despite my being a long-time emacs user, I was pleasantly surprised to learn that you can use elisp with find-and-replace.

Now at first, this may not seem like a big deal. You can do a lot with a plain vanilla find-and-replace (M-x replace-string and M-x query-replace (also bound to M-%)), and regex find-and-replaces (M-x replace-regexp and M-x query-replace-regexp (also bound to C-M-%)) are damn powerful. But sometimes, when a sed script won’t do, an elisp find-and-replace can save you a lot of pain.

To do an elisp find-and-replace, do a regular replace-regexp, and set the replacement expression to \, (backslash-comma) followed by an elisp expression. You can use backreferences \1 through \9 as string variables, and you can use \# as an integer variable that is the total number of replacements made so far.

Steve has a number of great examples which I’m not going to repeat here, so I encourage you to go over there and eat ’em up.

I was eager to try them out, and seeing as how Emacs 22 is over two and half years old, I figured my current Emacs install would be up-to-date. Not so – my MacBook was still running Emacs 21.2.1, which came installed when I bought it in 2006. Fortunately, with MacPorts installed (HIGHLY recommended for anyone running OS X), upgrading was almost as easy as running

sudo port install emacs

I did install instead of upgrade because my emacs install was the default one that came installed and I hadn’t migrated it into MacPorts yet. I said it was almost that easy because after it installed and I went to run it, the old Emacs 21 ran instead, even though the MacPorts binaries directory /opt/local/bin precedes /usr/bin in my $PATH. It turns out that bash uses a hash table, of which I was previously unaware, to cache where frequently used commands are located to avoid searching your $PATH frequently. To fix this, just run hash -d emacs to delete its binding for emacs (or hash -r to clear the entire table), and you’re good to go!

Comments are closed.