2

我搜索了许多 Stackoverflow 正则表达式帖子,但找不到我的答案。我正在使用以下内容查找给定$text字符串中的所有 URL:

$pattern = "#((http|https|ftp|ftps)://)?([a-zA-Z0-9\-]*\.)+[a-zA-Z0-9]{2,4}(/[a-zA-Z0-9=.?&-]*)?#";

(同意可能更精确/更有效/......但这不是问题......但是)。

现在使用此文本输入:

$text = "Website: www.example.com, ";
$text .= "Contact us: http://www.example.com/cu?t=contactus#anchor, ";
$text .= "Email: contact@example.com";

然后一个

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

将返回这些:

www.example.com
http://www.example.com/cu?t=contactus
example.com

最后一个example.com来自电子邮件,我希望能够排除它。
我尝试了很多组合[^@](?!@)...无济于事,我仍然收到电子邮件结果。

我能做的最好的事情是@在开头包含一个可选的,这样它就会返回@example.com,然后我循环我的结果以排除以@.

有没有更好的解决方案?一个不包含电子邮件子字符串的模式?

4

1 回答 1

1

不使用断言等太高级功能的示例解决方案:

<?php

$text = 'ftp://web.com, ';
$text .= "Website: www.example.com, ";
$text .= "Contact us: http://www.example.com/cu?t=contactus#anchor, ";
$text .= "Email: contact@example.com";

$base = "((http|https|ftp|ftps)://)?([a-zA-Z0-9\-]*\.)+[a-zA-Z0-9]{2,4}(/[a-zA-Z0-9=.?&-]*)?";

$matches = array(); preg_match_all("#$base#", $text, $matches); var_dump($matches[0]);
$matches = array(); preg_match_all("#\s($base)#", " $text", $matches); var_dump($matches[1]);

?>

输出:

array(4) {
  [0]=>
  string(13) "ftp://web.com"
  [1]=>
  string(15) "www.example.com"
  [2]=>
  string(37) "http://www.example.com/cu?t=contactus"
  [3]=>
  string(11) "example.com"
}
array(3) {
  [0]=>
  string(13) "ftp://web.com"
  [1]=>
  string(15) "www.example.com"
  [2]=>
  string(37) "http://www.example.com/cu?t=contactus"
}

只需检查 URL 之前的空格,但不要将其包含在子模式中。使用[^@]将不起作用,因为正则表达式只会匹配匹配的e其余部分 - 它们稍后将合并为单个匹配。[^@]xample.com

于 2013-03-07T13:18:04.783 回答