Earlier today I wanted to convert a bunch of Org meta data keywords to lower case notation, with the help of isearch-forward-regexp and query-replace-regexp. This included everything from special comments, like #+TITLE: to property drawers in the form of :PROPERTIES:. There were 340 such cases in my file and I was reluctant to do so manually. Thankfully, Emacs makes such a task fairly simple once you get past the essentials, because it lets you evaluate arbitrary Elisp forms for the replacement text. This includes the possibility of running some function on a matched regexp group. In this case that function was (downcase OBJECT).

First I needed a regular expression that would capture all targets. isearch-forward-regexp and its query-replace-regexp counterpart expect a single backslash for the escape character, so I ended up with this pattern:

^\(#\|:\)[^ ].*?:

If I were to test this in the buffer, I could use M-x re-builder, which however requires double backslashes (same for when you write Elisp code):

^\\(#\\|:\\)[^ ].*?:

Try this with any string in a buffer, say, Hello:

Confirm the operation and you should get HELLO. This works with multiple groups and can read a series of Elisp forms. An example with Hello world:

Which should give you hello World.

The elegant minimalism of the query-replace interface grants you the power to either replace each match one at a time or hit the exclamation mark (!) to answer “yes to all”. This is what I did to downcase all 340 matches. Voila! All of my Org file’s meta data were converted to lower case in one go.

Finally, I discovered query-replace-regexp-eval which saves you from adding the escaped comma operator for the replacement’s Elisp form. However its doc string reads thus:

Interactive use of this function is deprecated in favor of the
‘\,’ feature of ‘query-replace-regexp’.  For non-interactive use, a loop
using ‘search-forward-regexp’ and ‘replace-match’ is preferred.