#43532 [Opn->Csd]: preg_replace: Escaping \ and $n in 2nd arg
| From: | vrana@php.net | Date: | Fri, 07 Nov 2008 14:42:04 +0000 |
| Subject: | #43532 [Opn->Csd]: preg_replace: Escaping \ and $n in 2nd arg | ||
| References: | 1 | Groups: | php.doc.bugs |
| Request: | Send a blank email to doc-bugs+get-1455@lists.php.net to get a copy of this message | ||
ID: 43532
Updated by: vrana@php.net
Reported By: csaba at alum dot mit dot edu
-Status: Open
+Status: Closed
Bug Type: Documentation problem
PHP Version: Irrelevant
New Comment:
This bug has been fixed in the documentation's XML sources. Since the
online and downloadable versions of the documentation need some time
to get updated, we would like to ask you to be a bit patient.
Thank you for the report, and for helping us make our documentation
better.
"To use backslash in replacement, it must be doubled("\\\\" PHP
string)."
Previous Comments:
------------------------------------------------------------------------
[2007-12-08 12:28:13] csaba at alum dot mit dot edu
That passage concerns (backlashes in) regular expression ->patterns<-
and does not apply here. My example does not have any backslashes in
the pattern (which is the 1st argument to preg_replace). My report only
concerns backslashes in the replacement (which is the 2nd argument).
Csaba
By the way, the section that you quoted and the paragraph above it is
gramatically incorrect ("strings have special meaning of backslash" is
improper. In addition double backslashes are treated the same in all
three types of PHP strings (single quoted, double quoted, heredoc) so
the type of PHP string should not be qualified. Also, the use of the
word "write" is ambiguous (because when one writes "\\" one gets a
single backslash), and is particularly confusing as a result. I would
reword it thusly:
For example, to match a "*" character, the pattern should contain "\*"
(backslash asterisk). This applies whether or not the following
character would otherwise be interpreted as a meta-character. It is
always safe to precede a non-alphanumeric with backslash (\) to specify
that the character itself is being matched. In particular, to match a
backslash, the pattern should contain \\ (two backslashes).
Note: A backslash escapes the following backslash within PHP
strings. Thus, if \ has to be matched by a regular expression pattern
\\, then four backslahses (\\\\) are required in the php string. E.g.
preg_match("/\\\\/", $subject) matches a single backslash in $subject.
(If only the most offending sentence is to be changed, then it should
be reworded thusly: Backslash has special meaning within PHP strings.)
------------------------------------------------------------------------
[2007-12-08 09:51:11] felipe@php.net
The documentation says:
"Note: Single and double quoted PHP strings have special meaning of
backslash. Thus if \ has to be matched with a regular expression \\,
then "\\\\" or '\\\\' must be used in PHP code."
(Maybe the escape will be changed in this post)
Its mentioned in:
http://br2.php.net/manual/en/reference.pcre.pattern.syntax.php
------------------------------------------------------------------------
[2007-12-08 02:03:51] csaba at alum dot mit dot edu
Description:
------------
preg_replace("/x/", '\\\\', "axb")
=> a\b
This has been reported at least 5 times as a bug in PHP (bugs 11594,
12668, 17616, 34560, 10626), and each time the answer comes back that
it's not a bug in PHP, and to check the documentation.
There is nothing in the documentation to indicate this behaviour,
especially with no /e modifier, so the documentation should be revised.
I would suggest something like the below - edit to suit:
Csaba Gabor from Vienna
$replacement has two type of escaping: pairs of backslashes are
combined, and $n is a back reference to a captured (sub)pattern.
Example: To make a pure substitution without escaping effects, the
following may be used:
$subject = "xay";
$replacement = 'b\c\\d\\\e\\\\$0f\\\\\g';
// first one protects backslashes, 2nd one protects $
$aMap = array("/\\\\+/" => '$0$0', "/\\$/" =>
'\\\\$');
$rep = preg_replace(array_keys($aMap),
array_values($aMap),$replacement);
// protected replacement
$result = preg_replace("/(a)/", $rep, $subject);
// original, unprotected replacement
$res0 = preg_replace("/(a)/", $replacement, $subject);
$replacment => b\c\d\\e\\$0f\\\g
$rep => b\\c\\d\\\\e\\\\\$0f\\\\\\g
$result => xb\c\d\\e\\$0f\\\gy
$res0 => xb\c\d\e\af\\gy
------------------------------------------------------------------------
--
Edit this bug report at http://bugs.php.net/?id=43532&edit=1