php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #18442 Numbered backreferences don't work properly
Submitted: 2002-07-19 19:54 UTC Modified: 2002-09-11 09:44 UTC
From: joeasdf at hotmail dot com Assigned: andrei (profile)
Status: Closed Package: PCRE related
PHP Version: 4.2.1 OS: Win2K (NT 5.0 build 2195)
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: joeasdf at hotmail dot com
New email:
PHP Version: OS:

 

 [2002-07-19 19:54 UTC] joeasdf at hotmail dot com
I want to reformat a date string from mm/yy to yymmdd (e.g. replace "67/89" with "896701".  The problem is that I need to be able to separate my numbered backreferences but NOT separate the output text.  In perl, this would be written as "${2}${1}01", but PHP does not allow curly braces in the numbered reference.

$text = '67/89';
$patt =  '!(\d\d)/(\d\d)(?=\t)!';
$repl = '{$2}${1}01';

echo preg_replace($patt, $repl, $text);
// outputs "{89}${1}01"

The PHP manual for preg_replace says that numbered backreferences work for numbers from 0 - 99, so I figured I'd try two-digit backreference numbers to force the separation between $1 and 01:

$repl = '$02$0101';

Here's where the real bug lies --  $02 is substituted properly, but the 2 and 1 are still inserted into the output!  Only '$0' is removed from the replacement pattern:

echo preg_replace($patt, $repl, $text);
// outputs "89267101"

The third character, 2, is the 2nd digit of $02.  Similarly, the 1 immediately following 67 is from $01.

The only way to get around this problem is to use preg_match() and manually create the string using the $matches array.

if(preg_match('(.*)' . $patt . '(.*)', $text, $matches))
{
   $text  = $matches[1]; // everything before $patt
   $text .= $matches[3]; // our old $2
   $text .= $matches[2]; // our old $1
   $text .= '01';        // from the original replacement
   $text .= $matches[4]; // everything after $patt
}

Seems a huge waste...

Take care,

nik

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2002-07-20 07:55 UTC] leblanc at anywhere dot com
and what about doing :

$repl=substr($text,3,2).substr($text,0,2)."01";

??

this would be much faster imo. For that case I dun see the need for a regular exp heh

/Leblanc
 [2002-07-22 18:16 UTC] joeasdf at hotmail dot com
The reason I can't use substr is because I am parsing strings of arbitrary length, where one or more dates of this format may appear.  I posted the simplest script/example I could to describe the bug without adding anything extra to detract from it.

Take care,

nik
 [2002-09-11 09:44 UTC] andrei@php.net
I added the ability to use Perl-style ${n} references. This should take care of your problem.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 21:01:28 2024 UTC