Emacs: how do I replace-regexp with a lisp function in a defun?

Viewed 4878

For example I want to make all text in parenthesis, (), UPCASE. It's trivial to do the following interactively:

M-x query-replace-regexp
replace: "(\(.+?\))"
with   : "(\,(upcase \1))"

Instead I want to write a defun which will do that:

(defun upcs ()
  (interactive)
  (goto-char 1)
  (while (search-forward "(\\(.+?\\))" nil t) (replace-match "(\\,(upcase \\1))" t nil)))

but it doesn't work! While the following works (it appends foo and bar to the parenthesized texts):

(defun HOOK ()
  (interactive)
  (goto-char 1)
  (while (search-forward-regexp "(\\(.+?\\))" nil t) (replace-match "(foo \\1 bar)" t nil)))
5 Answers

This was very useful, thanks all.

In the interest of putting more examples on the web, I went from this:

(replace-regexp "\([\%\)\”\"]\..?\)[0-9]+" "\1")

(which didn't work, but which used the regexps that did work in interactive mode)

to this:

(while (re-search-forward "\\([\\%\\\"\\”]\\)\\.?[0-9]+" nil t)
    (replace-match (match-string 1) t nil))

I needed three backslashes before the internal quotation mark.

The interactive regex-based replacement functions cannot change the case but otherwise work fine by default: the case-replace variable needs to be set to nil (default: t). Then interactive replacements then will properly work with ,(upcase \1) and friends.

Reference: See discussion on the emacs-berlin mailing list: https://mailb.org/pipermail/emacs-berlin/2021/000840.html

Related