ID: 15166
Updated by: derick
Old Summary: preg_replace issue when \\1 is followed by 1
Reported By: [EMAIL PROTECTED]
Status: Open
Bug Type: Documentation problem
Operating System: WINDOWS 2000
PHP Version: 4.1.1
New Comment:

'{$1}' or "{\$1}"


Previous Comments:
------------------------------------------------------------------------

[2002-01-24 11:27:17] [EMAIL PROTECTED]

I tried the syntax {$1} with PHP 4.1.1 as below:
1/
$test=preg_replace("/(<\!DOCTYPE\s+map\s+SYSTEM\s+\"http:\/\/)[^\/]+/i","{$1}$servname:$servport",$test);


It gives me the following error:
Parse error: parse error, expecting `T_VARIABLE' or `'$'' in
C:\inetpub\wwwroot\bug2.php on line 33

2/ Escaping the first brace:
$test=preg_replace("/(<\!DOCTYPE\s+map\s+SYSTEM\s+\"http:\/\/)[^\/]+/i","\{$1}$servname:$servport",$test);


The result is the following one:
test2 RESULT  :{<!DOCTYPE map SYSTEM
"http://}10.0.9.91:81/Gui/dtd/deployment/dbmap.dtd";>
It is escaping properly the 1 contained in $servername but keep the
braces.

3/ The only way I found to escape $servername is by using the value 99
as follow:
$test=preg_replace("/(<\!DOCTYPE\s+map\s+SYSTEM\s+\"http:\/\/)[^\/]+/i","\\1\\99$servname:$servport",$test);

991 is not taken because of the limitation to 99 different strings. I
just need to make sure I am not using 99 different parentheses which is
pretty huge.


------------------------------------------------------------------------

[2002-01-22 17:26:53] [EMAIL PROTECTED]

You'd either need to escape the number after your reference, ie: \\1\1
or if you're using PHP 4.0.4 or later, you can use {$1} in the
replacement portion of preg_replace (see documentation).

------------------------------------------------------------------------

[2002-01-22 15:00:59] [EMAIL PROTECTED]

What do you think about the following suggestions:

A/ Counting how many string are enclosed by parentheses.
preg_replace("/(......)test(....)/","\\110.0.0.173",$test);
=> expecting 2 strings enclosed
Then parse the value following \\ and keep only the one lower than the
max expected.
Expecting 2:
\\1 OK
\\11 TOO high, keep \\1

I do not know what the impact might be in term of performance.
=> Implementing a way to escape might be faster.

B/ Using a different notation to escape the string following \\1 (brace
for example)
preg_replace("/(......)test(....)/","\\{1}10.0.0.173",$test);

Thanks for your prompt answer, that was quick :-)

------------------------------------------------------------------------

[2002-01-22 14:44:12] [EMAIL PROTECTED]

\\11 matches the 11th string enclosed by parenthesis.
Can't find anything about escaping it. Reclassified as a documentation
problem.

------------------------------------------------------------------------

[2002-01-22 11:47:39] [EMAIL PROTECTED]

1/DETAIL:
When I am using preg_replace with \\1 to keep the first iteration
retrieved, if \\1 is followed by a string starting by 1, this is
removing the 1 of the string and losing the content of \\1.

Here is a script to show 4 test cases. The test2 and test4 failed
because of this issue. 

The test3 is the solution i found to avoid this issue by inserting any
character different from 1 just after \\1.

Thanks in advance for your help.
Pierre

<?
$value='<!DOCTYPE map SYSTEM
"http://localhost/Gui/dtd/deployment/dbmap.dtd";>';
$servname='10.0.9.91';
$servport='81';

// TITLE
print "<HR><CENTER>\n";
print("<b>BUG with <font color='red'>preg_replace</font> and <font
color='red'>\\\\1</font> followed by a variable starting by
1</b><BR><BR>\n");
print("<B> WINDOWS 2000 platform, PHP version 4.1.1<BR></b>\n");
print("<xmp>ORIGINAL VALUE:".$value."</xmp>\n");
print "<HR></CENTER>\n";

// TEST 1 with servname='localhost';
$testservname='localhost';
$test=$value;
$expected='<!DOCTYPE map SYSTEM
"http://'.$testservname.':'.$servport.'/Gui/dtd/deployment/dbmap.dtd">';
$test=preg_replace("/(<\!DOCTYPE\s+map\s+SYSTEM\s+\"http:\/\/)[^\/]+/i","\\1$testservname:$servport",$test);

$status ='OK';
if ($test != $expected) $status='WRONG';

print "<xmp>\n";
print_r("test1 SERVER NAME:$testservname        SERVER PORT:$servport\n");
print_r("test1 OPERATION:
\$test=preg_replace(\"/(<\!DOCTYPE\s+map\s+SYSTEM\s+\"http:\/\/)[^\/]+/i\",\"\\\\1\$testservname:\$servport\",\$test);"."\n");

print_r("test1 RESULT  :".$test."\n");
print_r("test1 EXPECTED:".$expected."\n");
print "</xmp><BR>\n";
print("test1 STATUS  :<font
color='red'>".$status."</font><BR><HR>\n");

//TEST 2 with servname = '10.0.9.91';
$test=$value;
$testservname=$servname;
$expected='<!DOCTYPE map SYSTEM
"http://'.$testservname.':'.$servport.'/Gui/dtd/deployment/dbmap.dtd">';
$test=preg_replace("/(<\!DOCTYPE\s+map\s+SYSTEM\s+\"http:\/\/)[^\/]+/i","\\1$servname:$servport",$test);

$status ='OK';
if ($test != $expected) $status='WRONG';

print "<xmp>\n";
print_r("test2 SERVER NAME:$testservname        SERVER PORT:$servport\n");
print_r("test2 OPERATION:
\$test=preg_replace(\"/(<\!DOCTYPE\s+map\s+SYSTEM\s+\"http:\/\/)[^\/]+/i\",\"\\\\1\$testservname:\$servport\",\$test);"."\n");

print_r("test2 RESULT  :".$test."\n");
print_r("test2 EXPECTED:".$expected."\n");
print"</xmp><BR>\n";
print("test2 STATUS  :<font
color='red'>".$status."</font><BR><HR>\n");


// TEST3
$test=$value;
$testservname=$servname;
$expected='<!DOCTYPE map SYSTEM
"http://'.$testservname.':'.$servport.'/Gui/dtd/deployment/dbmap.dtd">';
$test=preg_replace("/(<\!DOCTYPE\s+map\s+SYSTEM\s+\")http:\/\/[^\/]+/i","\\1http://$servname:$servport",$test);

$status ='OK';
if ($test != $expected) $status='WRONG';

print "<xmp>\n";
print_r("test3 SERVER NAME:$testservname        SERVER PORT:$servport\n");
print_r("test3 OPERATION:
\$test=preg_replace(\"/(<\!DOCTYPE\s+map\s+SYSTEM\s+\")http:\/\/[^\/]+/i\",\"\\\\1http://\$testservname:\$servport\",\$test);"."\n");

print_r("test3 RESULT  :".$test."\n");
print_r("test3 EXPECTED:".$expected."\n");
print "</xmp><BR>\n";
print("test3 STATUS  :<font
color='red'>".$status."</font><BR><HR>\n");


// TEST4
$test="this is a test with any string";
$testservname='1234567890';
$expected='this is a '.$testservname.':'.$servport.' with any string';
$test=preg_replace("/(this is a
)test/i","\\1$testservname:$servport",$test);
$status ='OK';
if ($test != $expected) $status='WRONG';

print "<xmp>\n";
print_r("test4 SERVER NAME:$testservname        SERVER PORT:$servport\n");
print_r("test4 OPERATION: \$test=preg_replace(\"/(this is
a)test/i\",\"\\\\1\$testservname:\$servport\",\$test);"."\n");
print_r("test4 RESULT  :".$test."\n");
print_r("test4 EXPECTED:".$expected."\n");
print "</xmp><BR>\n";
print("test4 STATUS  :<font
color='red'>".$status."</font><BR><HR>\n");

// General comments
print "<BR><b>COMMENTS</b>: test2 and test4 failed<BR>\n";
print "The issue happens only if \$testservname start by 1. For example
with test1 the substitution works since the value of \$testservname
does not start by 1\n";
print "<HR>\n";
?>

------------------------------------------------------------------------



Edit this bug report at http://bugs.php.net/?id=15166&edit=1


-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]

Reply via email to