[英]preg_match_all and foreach only replacing last match
I have the following code, which should make plain text links clickable.我有以下代码,它应该使纯文本链接可点击。 However, if there are several links, it only replaces the last one.
但是,如果有多个链接,它只会替换最后一个。
Code:代码:
$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);
}
Result:结果:
http://www.google.com
http://www.yahoo.com
http://www.microsoft.com/ <-- only this one is clickable
Expected result:预期结果:
Where is my error?我的错误在哪里?
if there are several links it only replaces the last one
如果有多个链接,它只会替换最后一个
Where is my error?
我的错误在哪里?
Actually, it's replacing all 3 links, but it replaces the original string each time.实际上,它正在替换所有 3 个链接,但每次都会替换原始字符串。
foreach($matches[0] AS $match)
{
$html_url = '<a href="' . $match . '" target="_blank">' . $match . '</a>';
$match_string = str_replace($match, $html_url, $match_code);
}
The loop is executed 3 times, each time it replaces 1 link in $match_code
and assigns the result to $match_string
.循环执行 3 次,每次替换
$match_code
1 个链接并将结果分配给$match_string
。 On the first iteration, $match_string
is assigned the result with a clickable google.com
.在第一次迭代中,
$match_string
被分配了一个可点击的google.com
的结果。 On the second iteration, $match_string
is assigned with a clickable yahoo.com
.在第二次迭代中,
$match_string
被分配了一个可点击的yahoo.com
。 However, you've just replaced the original string, so google.com
is not clickable now.但是,您刚刚替换了原始字符串,因此现在无法点击
google.com
。 That's why you only get your last link as a result.这就是为什么您只能获得最后一个链接的原因。
There are a couple of things you may also want to correct in your code:您可能还想在代码中更正以下几点:
#<pre[\\s\\S]*</pre>#U
is better constructed as #<pre.*</pre>#Us
.#<pre[\\s\\S]*</pre>#U
最好构造为#<pre.*</pre>#Us
。 The class [\\s\\S]*
is normally used in JavaScript, where there is no s
flag to allow dots matching newlines.[\\s\\S]*
通常用于 JavaScript,其中没有s
标志来允许点匹配换行符。https?://\\S+
.https?://\\S+
。 I'll also link you to some alternatives here .preg_match_all()
calls and 1 str_replace()
call for the same text, where you could wrap it up in 1 preg_replace()
.preg_match_all()
调用和 1 个str_replace()
调用,您可以将它包装在 1 个preg_replace()
。 Code代码
$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);
Regex正则表达式
\\G
Always from the first matching position in the subject. \\G
总是从主题中的第一个匹配位置开始。(?:(?!\\A)|.*<pre)
Matches the first <pre
tag from the beggining of the string, or allows to get the next <pre
tag if no more URLs found in this tag. (?:(?!\\A)|.*<pre)
匹配字符串开头的第一个<pre
标签,或者如果在此标签中找不到更多 URL,则允许获取下一个<pre
标签。(?:(?!</pre>).)*)
Consumes any chars inside a <pre>
tag. (?:(?!</pre>).)*)
使用<pre>
标签内的任何字符。(https?://\\S+?)
Matches 1 URL. (https?://\\S+?)
匹配 1 个 URL。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.