使用preg_replace命名反向引用

13

相当简单;我似乎找不到有关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) 是不是不被支持。是语法问题还是不存在此功能?

4个回答

14

它们存在:

http://www.php.net/manual/zh/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);

1
谢谢Dimitry;如果答案不支持,那么我将简单地恢复到编号引用。 - Dan Lugg
2
你可以使用 preg_replace_callback 函数来进行命名匹配。 - Dimitry
啊,从数组参数……好知道,但这里不适合。该死,真是个烦人的事。 - Dan Lugg

7

preg_replace不支持命名反向引用。

preg_replace_callback支持命名反向引用,但在PHP 5.3之后,所以预计在PHP 5.2及以下版本上会失败。


1
命名子模式的反向引用可以使用 (?P=name) 或者 PHP 5.2.2 开始支持的 \k<name> 或 \k'name' 来实现。此外,PHP 5.2.4 还增加了对 \k{name} 和 \g{name} 的支持。这段引述(来自Dimitry提供的链接)仅适用于 preg_match()preg_match_all(),是吗? - Dan Lugg
1
是的,它只适用于该模式。 - Thai

2

preg_replace目前还不支持命名子模式。


0
你可以使用这个:
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}或$+{name}作为引用。

参考链接(http://www.rexegg.com/regex-disambiguation.html#namedcapture


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接