If test-string is defined like so

(setq test-string "fooXbarXbazXextraYstuff")

then the regexp "^[^XY]+X" matches test-string:

(string-match "^[^XY]+X" test-string)
=> 0 (#o0, #x0, ?\C-@)

...but the same regexp with grouping parentheses added no longer matches:

(string-match "^\([^XY]+X\)" test-string)
=> nil

Simply adorable.

Given the behavior above, it is not surprising that

(replace-regexp-in-string "^\([^XY]+X\)+" "" test-string)

evaluates to the original value of test-string.

What regexp must I put in place of the ??? below

(replace-regexp-in-string ??? "" test-string)

so that the resulting value is the string "extraYstuff"?

(BTW, I'd love to know the official/documented rationale for the behavior shown above, if there is one.)

  • 2
    You need to escape the backslash, when it is inside string literal (as opposed to when you input the regular expression interactively). – wvxvw Jan 19 '16 at 16:01
  • 2
    Yes, escaping rules are tricky -- this is why I prefer to use rx in my elisp code. – Constantine Jan 22 '16 at 6:10
  • It's very useful when writing regexps to use M-x regexp-builder as it lets you see live how your changes take effect – rlazo Jan 22 '16 at 12:35

You need to escape the \ on your \(...\) to read \\(...\\):

(string-match "^\\([^XY]+X\\)" "fooXbarXbazXextraYstuff") ; => 0
  • Oh my god... Well, thanks & +1. (I'll accept your answer as soon as ESE lets me.) – kjo Jan 19 '16 at 16:03
  • 1
    @kjo: I make this mistake with great regularity. – Dan Jan 19 '16 at 16:05
  • 1
    Instead of bothering with backslash escapes yourself, consider using a tool like helm-regexp. As the Wiki page notes, it has several advantages, including instant feedback for your regexp on a buffer and a Helm action to add its string form to your kill ring. – Tianxiang Xiong Jan 22 '16 at 6:40

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.