Именованные обратные ссылки с preg_replace
Довольно просто; Я не могу найти ничего определенного относительно PHP 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);
Это тривиальный пример, но мне интересно, просто ли этот синтаксис (?P=name)
не поддерживается. Синтаксическая проблема или несуществующая функциональность?
Ответы
Ответ 1
Они существуют:
http://www.php.net/manual/en/regexp.reference.back-references.php
С preg_replace_callback:
function my_replace($matches) {
return '/user/profile/' . $matches['id'];
}
$newandimproved = preg_replace_callback('#^user/(?P<id>[^/]+)$#Di', 'my_replace', $string);
Или даже быстрее
$newandimproved = preg_replace('#^user/([^/]+)$#Di', '/user/profile/$1', $string);
Ответ 2
preg_replace
не поддерживает именованные обратные ссылки.
preg_replace_callback
поддерживает именованные обратные ссылки, но после PHP 5.3, поэтому ожидайте, что он завершится неудачей на PHP 5.2 и ниже.
Ответ 3
preg_replace
пока не поддерживает именованные подшаблоны.
Ответ 4
вы можете использовать это:
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);
}
то вы можете использовать либо \g<name> ${name} or $+{name}
как ссылку в операторе replace.
cf (http://www.rexegg.com/regex-disambiguation.html#namedcapture)