note 66344 deleted from function.preg-replace by bjori

From: Date: Sat, 01 Jul 2006 15:45:03 +0000
Subject: note 66344 deleted from function.preg-replace by bjori
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-114353@lists.php.net to get a copy of this message
Note Submitter: sep16 at psu dot edu Reason: bug ---- 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"; ?>

« previous php.notes (#114353) next »