PHP正则提取字符串URL异常:仅获一个错误结果而非两个URL
问题分析与解决
核心问题有两个:
1. 正则表达式匹配逻辑缺陷
你的正则#\bhttps?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#i存在两处问题:
- 末尾的
(?:\([\w\d]+\)|([^,[:punct:]\s]|/))强制要求URL结尾匹配额外字符,导致第一个URL的末尾/被错误单独捕获,同时第二个URL的纯数字结尾不符合该规则,直接被排除匹配。 [^,\s()<>]+对URL主体的限制,结合后续分组规则,缩小了合法URL的范围,漏掉了数字结尾的URL。
2. 匹配结果遍历错误
preg_match_all返回的$urls是二维数组:
$urls[0]存储所有完整匹配的URL$urls[1]存储正则中第一个捕获组的匹配内容
你遍历整个$urls数组,会把捕获组里的冗余字符(比如第一个URL后的/)也拼接到结果里,导致输出异常。
修正后的代码
$str = '2014 urmymuse Licensed to the public under http://creativecommons.org/licenses/by/3.0/ Verify at http://ccmixter.org/files/urmymuse/47486'; $urls_str = ""; // 简化正则,适配绝大多数HTTP/HTTPS URL的匹配需求 $matches = preg_match_all('#\bhttps?://[^\s<>]+#i', $str, $urls); if ($matches) { // 只遍历完整匹配的结果集合 foreach ($urls[0] as $url) { $urls_str = $urls_str . ' ' . $url; } } // 输出预期结果:"http://creativecommons.org/licenses/by/3.0/ http://ccmixter.org/files/urmymuse/47486" echo trim($urls_str);
正则说明
#\bhttps?://[^\s<>]+#i:
\b:匹配单词边界,避免URL与其他字符粘连https?://:兼容HTTP和HTTPS协议[^\s<>]+:匹配除空白符、<、>之外的所有字符,覆盖绝大多数合法URL的结尾场景i:忽略大小写,支持HTTPS/https等写法
内容的提问来源于stack exchange,提问作者AlwaysBeginner
相关产品推荐
相关产品推荐

