1

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.

4

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.

  • That fixed it but it seems neither \1 or \\1 is working as the replacement part. – Meng Lu Jun 24 '15 at 7:41
  • Works for me with "\\1replacedText" as the replacement string. – Sean Jun 24 '15 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 Jun 24 '15 at 13:44
  • \\1 does work. It was a faulty regexp that caused me to think it didn't, – Meng Lu Jun 24 '15 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, privacy policy and cookie policy

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