如何使用preg_replace并获得匹配?

时间:2012-01-14 17:58:10

标签: php regex

我有一个文本,其中包含以@符号开头的用户名。例如:

One day @john decided to ask @jane out.

我想用链接替换所有用户名的出现,为了举例说明我想用@ user替换@user,例如:

One day link-john decided to ask link-jane out.

可以使用以下命令完成:

preg_replace('`@([a-zA-Z0-9]{2,15})`', 'link-$1', $text);

此外,我想获得像preg_match所做的所有匹配的数组,但我无法,因为preg_replace似乎没有提供该数组。实现这一目标的最有效方法是什么?我觉得做preg_match后来preg_replace会浪费资源,不是吗?

如果您觉得有更好的方法可以实现这一目标,我将非常感谢您的反馈。

谢谢!

2 个答案:

答案 0 :(得分:2)

您可以使用preg_replace_callback

<pre>
<?php

$arr = array();

function linker( $matches ) {
    global $arr;
    $arr[] = $matches[1];
    return "link-{$matches[1]}";
}

$text = "One day @john decided to ask @jane out.";
$result = preg_replace_callback('`@([a-zA-Z0-9]{2,15})`', "linker", $text);

echo $result . "\n";    
print_r( $arr );
?>
</pre>

结果:

One day link-john decided to ask link-jane out.
Array
(
    [0] => john
    [1] => jane
)

如果您使用的是PHP 5.3,则可以使用匿名函数使其更加清晰。

答案 1 :(得分:2)

另一种使用现代5.3语法的preg_replace_callback变体:

$str = "One day @john decided to ask @jane out.";

$matches = array();
$str = preg_replace_callback('`@([a-zA-Z0-9]{2,15})`', function($m) use(&$matches) {
    $matches[] = $m;
    return $m[1] . '-link';
}, $str);

echo '<pre>'; print_r($matches); echo '</pre>';

输出:

Array
(
    [0] => Array
        (
            [0] => @john
            [1] => john
        )

    [1] => Array
        (
            [0] => @jane
            [1] => jane
        )

)