2012-01-14 64 views
0

我有一个文本,其中包含用@符号前缀的用户名。例如:如何使用preg_replace并获取匹配?

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会浪费资源,不是吗?

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

谢谢!

+0

没有,有没有更好的选择。您可以使用'preg_replace_callback'来替换和组装回调中的匹配项。但是这并不符合“更好”的要求。 - 关于资源,在分析后总是优化*。 – mario 2012-01-14 18:07:05

回答

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,可以让这个更清洁用匿名函数。

+0

清洁你的意思是我不必使用全局$ arr; ? – DavidW 2012-01-14 18:27:15

+0

@Leo是的,如果你有PHP 5.3,绝对使用匿名函数就像其他答案一样。我发布了这个版本因为我不确定你有5.3。 – Esailija 2012-01-14 18:32:53

+0

非常感谢。 – DavidW 2012-01-14 18:40:17

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 
     ) 

) 
+0

这个版本会更有利,因为我不需要使用全球声明“global $ arr;” ? – DavidW 2012-01-14 18:25:29

+0

当然,使用'全球'是相当古老的风格。 PHP 5.3给了我们新的机会。虽然使用全局是另一种方式。你决定什么适合你。 – dfsq 2012-01-14 18:37:39

+0

非常感谢。 – DavidW 2012-01-14 18:40:31