Preg_split匹配超过它应该的

时间:2013-07-25 19:34:28

标签: php regex

代码:

    $pattern = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";
    $urls = array();
    preg_match($pattern, $comment, $urls);

    return $urls;

根据在线正则表达式测试人员的说法,这个正则表达式是正确的,应该可以正常工作:

http://regexr.com?35nf9

我正在输出$ links数组:

$linkItems = $model->getLinksInComment($model->comments);
//die(print_r($linkItems));
echo '<ul>';
foreach($linkItems as $link) {
    echo '<li><a href="'.$link.'">'.$link.'</a></li>';
}
echo '</ul>';

输出如下所示:

$ model-&gt;评论如下所示:

destined for surplus
RT#83015
RT#83617
http://google.com
https://google.com
non-link

生成的列表只是假设是链接,并且不应该是空行。我做了什么有问题,因为正则表达式似乎是正确的。

2 个答案:

答案 0 :(得分:1)

如果我理解正确,您应该在getLinksInComment函数中使用preg_match_all代替:

preg_match_all($pattern, $comment, $matches);

if (isset($matches[0])) {
    return $matches[0];
}
return array();    #in case there are no matches

preg_match_all获取字符串中的所有匹配项(即使字符串包含换行符),并将它们放入您提供的数组中作为第三个参数。但是,您的正则表达式的捕获组(例如(http|https|ftp|ftps))匹配的任何内容也会放入您的$matches数组中(如$matches[1],依此类推)。这就是为什么你想只返回$matches[0]作为你的最后一系列匹配。

我刚刚运行了这段确切的代码:

$line = "destined for surplus\n
RT#83015\n
RT#83617\n
http://google.com\n
https://google.com\n
non-link";

$pattern = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";
preg_match_all($pattern, $line, $matches);

var_dump($matches);

并得到了我的输出:

array(3) {
  [0]=>
  array(2) {
    [0]=>
    string(17) "http://google.com"
    [1]=>
    string(18) "https://google.com"
  }
  [1]=>
  array(2) {
    [0]=>
    string(4) "http"
    [1]=>
    string(5) "https"
  }
  [2]=>
  array(2) {
    [0]=>
    string(0) ""
    [1]=>
    string(0) ""
  }
}

答案 1 :(得分:0)

您的评论结构为多行,其中一些包含您感兴趣的网址,而不包含任何其他内容。在这种情况下,你不需要使用任何类似于正则表达式灾难的东西来尝试从完整的评论文本中选择URL;您可以改为换行,并分别检查每一行以查看它是否包含URL。因此,您可以实现更可靠的getLinksInComment()

function getLinksInComment($comment) {
    $links = array();
    foreach (preg_split('/\r?\n/', $comment) as $line) {
        if (!preg_match('/^http/', $line)) { continue; };
        array_push($links, $line);
    };
    return $links;
};

通过适当的调整作为对象方法而不是裸露的功能,这应该完全解决您的问题并让您自由地度过一天。