index rss mastodon twitter github linkedin email
Álvaro Ramírez

Álvaro Ramírez

27 June 2021 Emacs: smarter search and replace


Not long ago, I made a note to go back and read Mac for Translators's Emacs regex with Emacs lisp post. The author highlights Emacs's ability to apply additional logic when replacing text during a search-and-replace session. It does so by leveraging elisp expressions.

Coincidentally, a redditor recently asked What is the simplest way to apply a math formula to all numbers in a buffer/region? Some of the answers also point to search and replace leveraging elisp expressions.

While I rarely need to apply additional logic when replacing matches, it's nice to know we have options available in our Emacs toolbox. This prompted me to check out replace-regexp's documentation (via M-x describe-function or my favorite M-x helpful-callable). There's lots in there. Go check its docs out. You may be pleasantly surprised by all the features packed under this humble function.

For instance, \& expands to the current match. Similarly, \#& expands to the current match, fed through string-to-number. But what if you'd like to feed the match to another function? You can use \, to signal evaluation of an elisp expression. In other words, you could multiply by 3 using \,(* 3 \#&) or inserting whether a number is odd or even with something like \,(if (oddp \#&) "(odd)" "(even)").

Take the following text:


We can label each value "(odd)" or "(even)" as well as multiply by 3, by invoking replace-regexp as follows:

M-x replace-regexp

[PCRE] Replace regex:


Replace regex [-0-9.]+:

\& \,(if (oddp \#&) "(odd)" "(even)") x 3 = \,(* 3 \#&)

1 (odd) x 3 = 3
2 (even) x 3 = 6
3 (odd) x 3 = 9
4 (even) x 3 = 12
5 (odd) x 3 = 15
6 (even) x 3 = 18

It's worth noting that replace-regexp's cousin query-replace-regexp also handles all this wonderful magic.

Happy searching and replacing!