【问题标题】:PHP Regex URL parsing issues preg_replacePHP Regex URL 解析问题 preg_replace
【发布时间】:2013-05-07 05:01:34
【问题描述】:

我有一个自定义标记解析功能,多年来一直运行良好。我最近发现了一个以前没有注意到的错误,并且我无法修复它。如果有人可以帮助我,那就太棒了。因此,我有一个自定义构建的论坛和基于文本的 MMORPG,并且每个输入都经过净化和解析以获取 bbcode 之类的标记。它还会解析 URL 并将它们变成合法链接,这些链接会转到退出页面,并带有免责声明,表明您将离开该站点......所以我遇到的问题是,当我用户在一个页面中发布多个 URL 时文本框(假设 \n 分隔)它只会将所有其他 URL 转换为链接。这是 URL 的解析器:

$markup = preg_replace("/(^|[^=\"\/])\b((\w+:\/\/|www\.)[^\s<]+)" . "((\W+|\b)([\s<]|$))/ei", '"$1<a href=\"out.php?".shortURL("$2")."\" target=\"_blank\">".shortURL("$2")."</a>$4"', $markup);

如您所见,它调用了一个 PHP 函数,但这不是这里的问题。然后将整个文本块同时传递到这个 preg_replace 中,而不是逐行或任何其他方式。

  1. 如果有更简单的方式来编写此 preg_replace,请告诉我
  2. 如果您能弄清楚为什么这只是解析所有其他 URL,这就是我的最终目标

输入示例:

http://skylnk.co/tRRTnb
http://skylnk.co/hkIJBT
http://skylnk.co/vUMGQo 
http://skylnk.co/USOLfW 
http://skylnk.co/BPlaJl 
http://skylnk.co/tqcPbL
http://skylnk.co/jJTjRs
http://skylnk.co/itmhJs
http://skylnk.co/llUBAR
http://skylnk.co/XDJZxD

示例输出:

<a href="out.php?http://skylnk.co/tRRTnb" target="_blank">http://skylnk.co/tRRTnb</a>
<br>http://skylnk.co/hkIJBT
<br><a href="out.php?http://skylnk.co/vUMGQo" target="_blank">http://skylnk.co/vUMGQo</a> 
<br>http://skylnk.co/USOLfW 
<br><a href="out.php?http://skylnk.co/BPlaJl" target="_blank">http://skylnk.co/BPlaJl</a> 
<br>http://skylnk.co/tqcPbL
<br><a href="out.php?http://skylnk.co/jJTjRs" target="_blank">http://skylnk.co/jJTjRs</a>
<br>http://skylnk.co/itmhJs
<br><a href="out.php?http://skylnk.co/llUBAR" target="_blank">http://skylnk.co/llUBAR</a>
<br>http://skylnk.co/XDJZxD
<br>

【问题讨论】:

  • 你能给出一个失败的测试用例吗?
  • 我已经更新了帖子。

标签: php regex preg-replace


【解决方案1】:

preg_replace 中的e 标志是deprecated。您可以使用preg_replace_callback 访问相同的功能。

i 标志在这里是无用的,因为\w 已经匹配大写和小写,并且您的模式中没有反向引用。

我设置了m 标志,这使得^$ 匹配一行的开头和结尾,而不是整个字符串的开头和结尾。这应该可以解决您匹配每隔一行的奇怪问题。

我还让一些组不捕获(?:pattern) - 因为更大的捕获组已经捕获了文本。

以下代码未经测试。我只在正则表达式测试器上测试了正则表达式。

preg_replace_callback(
    "/(^|[^=\"\/])\b((?:\w+:\/\/|www\.)[^\s<]+)((?:\W+|\b)(?:[\s<]|$))/m",
    function ($m) {
        return "$m[1]<a href=\"out.php?".shortURL($m[2])."\" target=\"_blank\">".shortURL($m[2])."</a>$m[3]";
    },
    $markup
);

【讨论】:

  • 哇,太棒了。使用 Regex 可以学到很多东西。感谢您的及时回复,并对我的延误表示歉意。
猜你喜欢
  • 1970-01-01
  • 2012-07-07
  • 2011-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-03
相关资源
最近更新 更多