2

我正在尝试为使用 PHP 的聊天客户端实现非常宽松的正则表达式匹配。

聊天客户端必须能够获取完整和不完整的 URL。

例如:

http://www.example.comwww.example.comexample.com

我已经设置了一个 preg_replace 来尝试实现这一目标:

$find = array("/([\w]+:\/\/[\w-?&;#~=\.\/\@]+[\w\/])/is","/(^(?!http:\/\/)[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,4}(\/?\S*)?)/is");
$replace = array( "<a target=\"_blank\" href=\"http://\\1\">\\1</a>","<a target=\"_blank\" href=\"\\1\">\\1</a>");
$output = preg_replace($find, $replace, $input); 

因此,目标是首先找到具有协议的“完整” URL,然后尝试查找没有协议的“惰性” URL。

目前它适用于“完整” URL,但“惰性” URL 不会被拾取。

4

2 回答 2

5

我不久前设置了类似的东西。我的想法是……任何以协议标识符或“www”开头的都是 URL,加上与以有效 TLD(两个字母或已知 gTLD)结尾的域匹配的任何内容,如果它后面跟着一个路径。域本身就是域。

$gtlds="com|net|org|biz|edu|gov|int|pro|xxx";
$gtlds+="|aero|arpa|asia|coop|museum|name|travel";
#$gtlds+="|xn-[a-z0-9]+";
$a = array(
  '/(f|ht)tps?:\/\/[^ ]+/',
  '/(ftp|www)\.[a-z0-9.-]+(/[^ ]*)/',
  "/([a-z0-9][a-z0-9-]*\.)+([a-z]{2}|$gtlds)\/[^ ]*/"
);

请注意,我是一个老派的正则表达式用户,所以这是 ERE,而不是现在所有孩子都在使用的花哨的 PREG 东西。

来自IANA的 gTLD 长得离谱。我已经更新了它,所以它在这个答案的时间是有效的,除了.XN--*. 如果愿意,您可以包含以模式开头的 TLD 列表.XN--,或者直接匹配它们并增加$gtlds变量。我从来没有遇到过简单地忽略它们的存在而引起的任何问题,所以这就是我的策略。

上述 RE 适合我的特定用途。我没有声称他们会为每一个不属于我的案件工作。(例如,如果引用了域或 URL,它们将包含尾随引号。这不是我必须处理的事情,所以我没有处理它。)

请注意,当您进行替换时,虽然您希望生成器锚点的 HREF 属性是您匹配或生成的 URL,但您可能希望将原始文本保持原样以进行布局和显示。

并且取决于您如何使用这些,单词边界可能会有所帮助......但您已经知道如何做到这一点。

于 2012-06-17T11:42:48.910 回答
1

因此,经过数小时的辛勤工作……我设法找到了一种相对简单的方法来匹配 http:// URL 和 www。URL,以便将它们变成锚。

这是最终的解决方案:

$output = preg_replace("/\b((http(s)?:\/\/)?(www\.[a-zA-Z0-9\/\\\:\?\%\.\&\;=#\-\_\!\+\~\,]*))/is","<a target=\"_blank\" href=\"http$3://$4\">$0</a>",$output);

感谢 tamous 的正则表达式。

于 2012-06-18T15:48:48.490 回答