2

I'd like to define a function to do a query-replace-regexp with a pattern I often use. When not using capture groups, it works:

(defun my-replace ()
    (interactive)
    (query-replace-regexp "[[:nonascii:][:ascii:]]*xxx" "replacedText" nil (point-min) (point-max)))

But I couldn't figure out how to use capture groups -- neither '\(\)' nor '()' works:

(defun my-replace ()
  (interactive)
  (query-replace-regexp "([[:nonascii:][:ascii:]]*)xxx" "\1replacedText" nil (point-min) (point-max)))


(defun my-replace ()
    (interactive)
    (query-replace-regexp "\([[:nonascii:][:ascii:]]*\)xxx" "\1replacedText" nil (point-min) (point-max)))

But when invoked with M-x query-replace-regexp, \([[:nonascii:][:ascii:]]*\)xxx would work.

2 Answers 2

5

In Emacs Lisp string literals, backslash is an escape character. To express a single literal backslash character, as required by many regular expression constructs, you need two backslashes, eg:

"\\([[:nonascii:][:ascii:]]*\\)xxx"

You don't need the extra backslashes when you run query-replace-regexp interactively because you're not entering a string literal, ie, an Emacs Lisp language construct; you're entering the characters of the regexp directly.

Try hitting M-: (eval-expression) and entering this expression:

"\(foo\)"

You'll see:

"(foo)"

...indicating that an escaped parenthesis in a string literal is the same as an unescaped parenthesis. So the regular expression engine was seeing parentheses without a preceding backslash, which match only themselves; they weren't starting or ending a capturing group as you expected.

4
  • That fixed it but it seems neither \1 or \\1 is working as the replacement part.
    – Meng Lu
    Commented Jun 24, 2015 at 7:41
  • Works for me with "\\1replacedText" as the replacement string.
    – Sean
    Commented Jun 24, 2015 at 7:50
  • Well explained, Sean. It is especially good that you mentioned why the extra backslashes are not used when interactive (not only not needed, but not usable, BTW).
    – Drew
    Commented Jun 24, 2015 at 13:44
  • \\1 does work. It was a faulty regexp that caused me to think it didn't,
    – Meng Lu
    Commented Jun 24, 2015 at 17:29
3

Use "\" to quote "\":

(defun my-replace ()
  (interactive)
  (query-replace-regexp "\\([[:nonascii:][:ascii:]]*\\)xxx" "\\1replacedText"
                        nil (point-min) (point-max)))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.