【发布时间】:2013-02-06 23:24:35
【问题描述】:
所以我正在构建一个小型 CMS,并且我想避免在内容编辑器中允许 HTML。出于这个原因,我想检测文本中的原始 URL 以及支持类似 BB 的标签,以便更好地自定义。
www.example.com
[link http://www.example.com]Click me[/link]
不幸的是,我对正则表达式还很陌生,我似乎无法使其正常工作。我在字符串上运行两个正则表达式:第一个检测原始 URL,第二个检测类似 BB 的 URL。后者似乎工作得很好,但第一个会干扰,并且也会转换包含在标签中的 URL。
我从找到here 的一段代码开始,并做了一些补充。
这是非标记网址的代码:
/* don't match URLs preceeded by '[link ' */
(?<!\[link\s)
(
/* match all combinations of protocol and www. */
(\bhttps?://www\.|\bhttps?://|(?<!//)\bwww\.)
/* match URL (no changes made here) */
([^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))
/* but don't match if followed by [/link] - THIS DOESN'T WORK */
(?!\[/link\])
)
www. 之前的负面回溯是因为/ 不是单词字符,没有它类似于
[link http://www.example.com]example[/link]
在http:// 之后仍然会匹配。
上面的正则表达式产生以下匹配(用http://gskinner.com/RegExr/测试,匹配是bold。我不得不在http://之后添加空格,因为我不允许发布更多的网址):
www.example.com
http://www.example.com
http://example.com
[链接http://www.example.com]no问题1[/link]
[链接www.example.com]没问题2[/link]
[链接http://www.example.com]http://www.example.com[/link]
我尝试移动否定的前瞻并玩弄括号(非常漫无目的),但没有成功。
为了完整起见,这里是标签匹配的正则表达式(似乎有效):
(?:\[link\s)(\bhttps?://|\bwww\.|\bhttps?://www\.)([^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))\](.*)(?:\[/link\])
我相信有人可以立即发现错误。
提前非常感谢!
【问题讨论】:
-
(?!\[/link\])前瞻将失败,因为 PCRE 将连续缩短之前的匹配以成功。您可能需要使 URL 匹配超级贪婪。尝试(?> ...)使其具有原子性。 -
您能详细说明一下吗?我尝试使各种组原子化,但没有成功(但我不确定我是否完全理解原子组)。
标签: php regex preg-replace-callback negative-lookahead