【问题标题】:How would one use preg_replace and obtaining matches too?如何使用 preg_replace 并获得匹配项?
【发布时间】:2012-01-14 17:58:09
【问题描述】:

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

One day @john decided to ask @jane out.

我想用链接替换所有出现的用户名,举例来说,我想用链接用户替换@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 会浪费资源,不是吗?

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

谢谢!

【问题讨论】:

  • 不,没有更好的选择。您可以使用preg_replace_callback 在回调中替换和组装匹配项。但这并不能算得上“更好”。 -- 关于资源,总是在 分析之后优化。

标签: php regex


【解决方案1】:

你可以使用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,则可以使用匿名函数使这更简洁。

【讨论】:

  • 更清洁的意思是我不必使用全局 $arr; ?
  • @Leo 是的,如果你有 php 5.3,一定要像其他答案一样使用匿名函数。我发布了这个版本,因为我不确定你有 5.3。
【解决方案2】:

另外一个 preg_replace_callback 变体使用现代 5.3 语法:

$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
        )

)

【讨论】:

  • 这个版本会不会更有利,因为我不需要使用全局声明“global $arr;” ?
  • 当然,使用global 是相当老派的风格。 PHP 5.3 为我们提供了新的机会。尽管使用全局是另一种方式。你决定什么适合你。
猜你喜欢
  • 2010-09-05
  • 1970-01-01
  • 2014-05-19
  • 2015-08-30
  • 1970-01-01
  • 2022-08-14
  • 2021-02-03
  • 1970-01-01
相关资源
最近更新 更多