2011-03-10 16 views
11

Bastante sencillo; Me parece que no puede encontrar nada definitiva con respecto a preg_replace() apoyo referencias hacia atrás con nombre de PHP:referencias hacia atrás nombran con preg_replace

// should match, replace, and output: user/profile/foo 
$string = 'user/foo'; 
echo preg_replace('#^user/(?P<id>[^/]+)$#Di', 'user/profile/(?P=id)', $string); 

Este es un ejemplo trivial, pero me pregunto si esta sintaxis, (?P=name) es simplemente no es compatible. ¿Problema sintáctico o funcionalidad inexistente?

Respuesta

10

existen:

http://www.php.net/manual/en/regexp.reference.back-references.php

Con preg_replace_callback:

function my_replace($matches) { 
    return '/user/profile/' . $matches['id']; 
} 
$newandimproved = preg_replace_callback('#^user/(?P<id>[^/]+)$#Di', 'my_replace', $string); 

O incluso más rápido

$newandimproved = preg_replace('#^user/([^/]+)$#Di', '/user/profile/$1', $string); 
+1

** Gracias Dimitry; ** Si la respuesta es no compatible * *, entonces yo simplemente voy a revertir a las referencias numeradas. – Dan

+1

Puede usar coincidencias con nombre con preg_replace_callback. – Dimitry

+0

Ah, desde la matriz de argumentos ... bueno saber, sin embargo no se ajusta a la finalidad aquí. Maldición, qué dolor en el culo. – Dan

1

preg_replace No se admite el sub-patrones nombrados todavía.

4

preg_replace no admite referencias hacia atrás con nombre.

preg_replace_callback soporta referencias hacia atrás con nombre, pero después de PHP 5.3, así que espera que falle en PHP 5.2 y por debajo.

+1

"referencias de nuevo a la sub-patrones nombrados pueden ser alcanzados por (? P = nombre) o, a partir de PHP 5.2.2, también por \ k o \ k'name'. Además PHP 5.2.4 añadió soporte para \ k {nombre } y \ g {nombre}. " Esta cita (desde el enlace proporcionado Dimitry) se aplica a 'preg_match()' y 'preg_match_all()' única, correcta? – Dan

+0

Sí, solo se aplica al patrón. – Thai

0

puede utilizar esto:

class oreg_replace_helper { 
    const REGEXP = '~ 
(?<!\x5C)(\x5C\x5C)*+ 
(?: 
    (?: 
     \x5C(?P<num>\d++) 
    ) 
    | 
    (?: 
     \$\+?{(?P<name1>\w++)} 
    ) 
    | 
    (?: 
     \x5Cg\<(?P<name2>\w++)\> 
    ) 
)? 
~xs'; 

    protected $replace; 
    protected $matches; 

    public function __construct($replace) { 
     $this->replace = $replace; 
    } 

    public function replace($matches) { 
     var_dump($matches); 
     $this->matches = $matches; 
     return preg_replace_callback(self::REGEXP, array($this, 'map'), $this->replace); 
    } 

    public function map($matches) { 
     foreach (array('num', 'name1', 'name2') as $name) { 
      if (isset($this->matches[$matches[$name]])) { 
       return stripslashes($matches[1]) . $this->matches[$matches[$name]]; 
      } 
     } 
     return stripslashes($matches[1]); 
    } 
} 

function oreg_replace($pattern, $replace, $subject) { 
    return preg_replace_callback($pattern, array(new oreg_replace_helper($replace), 'replace'), $subject); 
} 

continuación, puede utilizar cualquiera \g<name> ${name} or $+{name} como referencia en su declaración de reemplazar.

cf (http://www.rexegg.com/regex-disambiguation.html#namedcapture)

Cuestiones relacionadas