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
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
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 20:01:29 2024 UTC