regexlispcommon-lispcl-ppcre

cl-ppcre:regex-replace and backslashes in replacement


May be this questions is really stuped, but I'm stuck. How can I put backslashes in cl-ppcre:regex-replace-all replacement?

For example I just want to escape some characters like ' " ( ) etc, so I'm going to do with | replacement first, to see that matching is ok:

    CL-USER> (princ (cl-ppcre:regex-replace-all "(['\\(\\)\"])"
"foo \"bar\" 'baz' (test)" "|\\1"))
    PRINTED: foo |"bar|" |'baz|' |(test|)

Ok, let's put slash:

    CL-USER> (princ (cl-ppcre:regex-replace-all "(['\\(\\)\"])"
"foo \"bar\" 'baz' (test)" "\\\1"))
    PRINTED: foo "bar" 'baz' (test) ;; No luck

No, we nedd two slashes:

    CL-USER> (princ (cl-ppcre:regex-replace-all "(['\\(\\)\"])"
"foo \"bar\" 'baz' (test)" "\\\\1"))
    PRINTED: foo \1bar\1 \1baz\1 \1test\1 ;; Got slash, but not \1

Maybe like this?

(princ (cl-ppcre:regex-replace-all "(['\\(\\)\"])"
"foo \"bar\" 'baz' (test)" "\\\{1}"))
PRINTED: foo "bar" 'baz' (test) ;; Nope, no luck here

Of course, if I'll put space between slashes everithing is ok, but I don't need it

(princ (cl-ppcre:regex-replace-all "(['\\(\\)\"])"
"foo \"bar\" 'baz' (test)" "\\ \\1"))
PRINTED: foo \ "bar\ " \ 'baz\ ' \ (test\ )

So, how can i write to get foo \"bar\" \'baz\' \(test\) printed? Thanks.


Solution

  • Six Source Slashes

    CL-USER> (princ (cl-ppcre:regex-replace-all "(['\\(\\)\"])"
                                                "foo \"bar\" 'baz' (test)"
                                                "\\\\\\1"))
    foo \"bar\" \'baz\' \(test\)
    

    When you write the string in the source code, each slash is being used as an escape. You want the replacement text to be the sequence of characters \\1. To encode the first slash in the replacement (since CL-PPCRE is going to process slashes), CL-PPCRE needs to see the sequence of characters \\\1. The first two slashes encode the slash, and the third encodes the group number. To get that sequence of characters as a Lisp string, you have to write "\\\\\\1".