note 66344 added to function.preg-replace

From: 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

« previous php.notes (#111687) next »