note 66344 added to function.preg-replace
| From: | sep16 at psu dot edu | Date: | Fri, 19 May 2006 15:28:48 +0000 |
| Subject: | note 66344 added to function.preg-replace | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-111687@lists.php.net to get a copy of this message | ||
Re: preg_replace() with the /e modifier; handling escaped quotes.
I was writing a replacement pattern to parse HTML text which sometimes contained PHP variable-like
strings. Various initial solutions yeilded either escaped quotes or fatal errors due to these
variable-like strings being interpreted as poorly formed variables.
"Tim K." and "steven -a-t- acko dot net" provide some detailed discussion of
preg_replace's quote escaping in the comments below, including the use of str_replace() to
remove the preg_replace added slash-quote. However, this suggestion is applied to the entire text
AFTER the preg_match. This isn't a robust solution in that it is conceivable that the text
unaffected by the preg_replace() may contain the string \\" which should not be fixed.
Furthermore, the addition of escaped quotes within preg_replaces with multiple patterns/replacements
(with arrays) may break one of the following patterns.
The solution, then, must fix the quote-escaped text BEFORE replacing it in the target, and possibly
before it is passed to a function within the replacement code. Since the replacement string is
interpreted as PHP code, just use
str_replace('\\"','"','$1') where you need an unadulterated
$1 to appear. The key is to properly escape the necessary characters. Three variations appear in
the examples below, as well as a set of incorrect examples. I haven't seen this solution
posted before, so hopefully this will be helpful rather than covering old ground.
Try this example code:
<?php
/*
Using preg_replace with the /e modifier on ANY text, regardless of single
quotes, double quotes, dollar signs, backslashes, and variable interpolation.
Tested on PHP 5.0.4 (cli), PHP 5.1.2-1+b1 (cli), and PHP 5.1.2 for Win32.
Solution?
1. Use single quotes for the replacement string.
2. Use escaped single quotes around the captured text variable (\\'$1\\').
3. Use str_replace() to remove the escaped double quotes
from within the replacement code (\\" -> ").
*/
function _prc_function1($var1,$var2,$match) {
$match = str_replace('\\"','"',$match);
// ... do other stuff ...
return $var1.$match.$var2;
}
function _prc_function2($var1,$var2,$match) {
// ... do other stuff ...
return $var1.$match.$var2;
}
$v1 = '(';
$v2 = ')';
// Lots of tricky characters:
$text =
"<xxx>...\\$varlike_text[_'\\\\\\"\\\\\\"\\"\\\\'...</xxx>";
$pattern = '/<xxx>(.*?)<\\/xxx>/e';
echo $text . " Original.<br>\\n";
// Example #1 - Processing in place.
// returns (...$varlike_text['\\"""\\'...)
echo preg_replace(
$pattern,
'$v1 . str_replace(\\'\\\\"\\',\\'"\\',\\'$1\\') .
$v2',
$text) . " Escaped double quotes replaced with str_replace. (Good.)<br>\\n";
// Example #2 - Processing within a function.
// returns (...$varlike_text['\\"""\\'...)
echo preg_replace(
$pattern,
'_prc_function1($v1,$v2,\\'$1\\')',
$text) . " Escaped double quotes replaced in a function. (Good.)<br>\\n";
// Example #3 - Preprocessing before a function.
// returns (...$varlike_text['\\"""\\'...)
echo preg_replace(
$pattern,
'_prc_function2($v1,$v2,str_replace(\\'\\\\"\\',\\'"\\',\\'$1\\'))',
$text) . " Escaped double quotes replaced with str_replace before sending match to a function.
(Good.)<br>\\n";
// Example #4 - INCORRECT implementations
// a. returns (...$varlike_text[_'\\\\"\\\\"\\"\\'...)
// b. returns (...$varlike_text[_'\\\\"\\\\"\\"\\'...)
// c. returns (...$varlike_text[_'\\\\"\\\\"\\"\\'...)
// d. Causes a syntax+fatal error, unexpected T_BAD_CHARACTER...
echo preg_replace( $pattern, "\\$v1 . '$1' . \\$v2", $text)," Enclosed in
double/single quotes. (Wrong! Extra slashes.)<br>\\n";
echo preg_replace( $pattern, "\\$v1 . '\\$1' . \\$v2", $text)," Enclosed in
double/single quotes, $ escaped. (Wrong! Extra slashes.)<br>\\n";
echo preg_replace( $pattern, '$v1 . \\'$1\\' . $v2', $text)," Enclosed in
single/single quotes. (Wrong! Extra slashes.)<br>\\n";
echo preg_replace( $pattern, '$v1 . "$1" . $v2', $text)," Enclosed in
single quotes. (Wrong! Dollar sign in text is interpreted as variable
interpolation.)<br>\\n";
?>
----
Server IP: 216.194.113.175
Probable Submitter: 150.231.246.1
----
X-Spam-Status: No, hits=3.3 required=5.0 tests=DATE_MISSING,FROM_NO_LOWER,
HTML_MESSAGE autolearn=no version=2.64
----
Manual Page -- http://www.php.net/manual/en/function.preg-replace.php
Edit -- http://master.php.net/note/edit/66344
Del: integrated -- http://master.php.net/note/delete/66344/integrated
Del: useless -- http://master.php.net/note/delete/66344/useless
Del: bad code -- http://master.php.net/note/delete/66344/bad+code
Del: spam -- http://master.php.net/note/delete/66344/spam
Del: non-english -- http://master.php.net/note/delete/66344/non-english
Del: in docs -- http://master.php.net/note/delete/66344/in+docs
Del: other reasons-- http://master.php.net/note/delete/66344
Reject -- http://master.php.net/note/reject/66344
Search -- http://master.php.net/manage/user-notes.php