繁体   English   中英

preg_match_all 和 foreach 只替换最后一个匹配

[英]preg_match_all and foreach only replacing last match

我有以下代码,它应该使纯文本链接可点击。 但是,如果有多个链接,它只会替换最后一个。

代码:

$nc = preg_match_all('#<pre[\s\S]*</pre>#U', $postbits, $matches_code); 
foreach($matches_code[0] AS $match_code) 
{
    $match = null;
    $matches = null;
    $url_regex = '#https?://(\w*:\w*@)?[-\w.]+(:\d+)?(/([\w/_.]*(\?\S+)?)?)?[^<\.,:;"\'\s]+#'; 
    $n = preg_match_all($url_regex, $match_code, $matches);
    foreach($matches[0] AS $match)
    {
        $html_url = '<a href="' . $match . '" target="_blank">' . $match . '</a>';
        $match_string = str_replace($match, $html_url, $match_code);
    }
    $postbits = str_replace($match_code, $match_string, $postbits); 
}

结果:

http://www.google.com

http://www.yahoo.com

http://www.microsoft.com/ <-- only this one is clickable

预期结果:

http://www.google.com

http://www.microsoft.com/

我的错误在哪里?

如果有多个链接,它只会替换最后一个

我的错误在哪里?

实际上,它正在替换所有 3 个链接,但每次都会替换原始字符串。

foreach($matches[0] AS $match)
{
    $html_url = '<a href="' . $match . '" target="_blank">' . $match . '</a>';
    $match_string = str_replace($match, $html_url, $match_code);
}

循环执行 3 次,每次替换$match_code 1 个链接并将结果分配给$match_string 在第一次迭代中, $match_string被分配了一个可点击的google.com的结果。 在第二次迭代中, $match_string被分配了一个可点击的yahoo.com 但是,您刚刚替换了原始字符串,因此现在无法点击google.com 这就是为什么您只能获得最后一个链接的原因。


您可能还想在代码中更正以下几点:

  1. 正则表达式#<pre[\\s\\S]*</pre>#U最好构造为#<pre.*</pre>#Us [\\s\\S]*通常用于 JavaScript,其中没有s标志来允许点匹配换行符。
  2. 我不明白您为什么要使用该模式来匹配 URL。 我认为您可以简单地使用https?://\\S+ 我还将在这里为您提供一些替代方案。
  3. 您正在对同一文本使用 2 个preg_match_all()调用和 1 个str_replace()调用,您可以将它包装在 1 个preg_replace()

代码

$postbits = "
<pre>
http://www.google.com

http://w...content-available-to-author-only...o.com

http://www.microsoft.com/ <-- only this one clickable
</pre>";


$regex = '#\G((?:(?!\A)|.*<pre)(?:(?!</pre>).)*)(https?://\S+?)#isU';
$repl = '\1<a href="\2" target="_blank">\2</a>';

$postbits = preg_replace( $regex, $repl, $postbits);

ideone 演示

正则表达式

  • \\G总是从主题中的第一个匹配位置开始。
  • 第一组
    • (?:(?!\\A)|.*<pre)匹配字符串开头的第一个<pre标签,或者如果在此标签中找不到更多 URL,则允许获取下一个<pre标签。
    • (?:(?!</pre>).)*)使用<pre>标签内的任何字符。
  • 第 2 组
    • (https?://\\S+?)匹配 1 个 URL。

正则表达式可视化

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM