I think there are a few different things going on here. First, regarding the original post on Stack Overflow - I can’t reproduce the failure in the second example. For me, using SWI-Prolog 8.5.10, both calls work as expected:
?- use_module(library(pcre)).
true.
?- re_replace("_"/g, "QW", "a_b_c", Str).
Str = "aQWbQWc".
?- re_replace("_"/g, "\\\\_", "a_b_c", Str).
Str = "a\\_b\\_c". % no failure!
Unfortunately the SO user didn’t post any version information, so it’s hard to diagnose this. Perhaps the previous development version had some bugs because of the recent migration to pcre2?
Second, about the result of re_replace
when using backslashes: keep in mind that (SWI-)Prolog by default displays atoms, strings, etc. in quoted form and escapes any special characers inside - including backslashes themselves. So the string "a\\_b\\_c"
doesn’t actually contain any double backslashes - it’s just the quoted representation of the text a\_b\_c
.
You can reproduce this with your PHP example as well - you just have to explicitly ask PHP to quote the string:
php > var_export(preg_replace("#_#", "\\\\_", "a_b_c"));
'a\\_b\\_c'
Finally, about the note in the re_replace/4 documentation:
Because \
is an escape character inside strings, you need to write “\\\\
” to get a single backslash.
It is correct that you need to write four backslashes to get a single backslash, but the explanation is incomplete. In addition to Prolog’s use of \
for escaping in strings, PCRE itself also uses backslashes for escaping and character classes (inside regexes) and for capture group references (inside replacement patterns). That is why you need four backslashes - the string "\\\\"
is unescaped by Prolog to the text \\
, and that is again unescaped by PCRE to the literal character \
.