我正在尝试编写一个正则表达式,它将在纯文本字符串中找到URL,以便我可以用锚标记包装它们。我知道有expressions already available for this,但我想创建自己的,主要是因为我想知道它是如何工作的。
如果我的正则表达式失败,它不会破坏任何东西,我的计划是写一些相当简单的东西。到目前为止,这意味着:1)在单词的开头匹配“www”或“http”2)保持匹配直到单词结束。
我能做到这一点,AFAICT。我有这个:\b(http|www).?[^\s]+
适用于foo www.example.com bar http://www.example.com
等。
问题在于,如果我给它foo www.example.com, http://www.example.com
,它会认为逗号是URL的一部分。
所以,如果我要使用一个表达式来执行此操作,我需要更改“...并在看到空格时停止”到“...”并在空格之前看到空格或标点符号时停止”。 这是我不确定该怎么做。
目前,我正在考虑运行的解决方案只是添加另一个测试 - 匹配URL,然后在下一行移动任何偷偷摸摸的标点符号。这不是那么优雅。
注意:我是用PHP编写的。
除此之外:为什么在上面的表达式中用\s
替换\b
似乎不起作用?
ETA:
谢谢大家!
根据Explosion Pills的建议,这是我最终得到的结果:
function add_links( $string ) {
function replace( $arr ) {
if ( strncmp( "http", $arr[1], 4) == 0 ) {
return "<a href=$arr[1]>$arr[1]</a>$arr[2]$arr[3]";
} else {
return "<a href=" . "http://" . $arr[1] . ">$arr[1]</a>$arr[2]$arr[3]";
}
}
return preg_replace_callback( '/\b((?:http|www).+?)((?!\/)[\p{P}]+)?(\s|$)/x', replace, $string );
}
我添加了一个回调,以便所有链接都以http://开头,并且做了一些处理标点符号的方法。
这可能不是最好的做事方式,但它确实有效。我在最后一段时间里对此有了很多了解,但还有更多需要学习的地方!
答案 0 :(得分:10)
preg_replace('/
\b # Initial word boundary
( # Start capture
(?: # Non-capture group
http|www # http or www (alternation)
) # end group
.+? # reluctant match for at least one character until...
) # End capture
( # Start capture
[,.]+ # ...one or more of either a comma or period.
# add more punctuation as needed
)? # End optional capture
(\s|$) # Followed by either a space character or end of string
/x', '<a href="\1">\1</a>\2\3'
......可能就是你想要的。我认为它仍然不完美,但至少应该能满足您的需求。
除此之外:我认为这是因为\b
也匹配标点符号
答案 1 :(得分:2)
您可以使用positive lookahead assertion:
来实现此目的\b(http:|www\.)(?:[^\s,.!?]|[,.!?](?!\s))+
表示匹配任何内容,但空白,.!?
或匹配,.!?
时没有空格。
除此之外:word boundary不是字符或一组字符,您不能将其放入字符类中。它是一个零宽度断言,匹配从单词字符到非单词字符的变化。在这里,我相信,字符类中的\b
被解释为退格字符(字符串转义序列)。
答案 2 :(得分:1)
问题可能出在点上,这意味着正则表达式中的“任何字符”。你可能不得不逃避它:
\b(http|www)\.?[^\s]+
然后,问号意味着0或1,所以你说“可选点”不是你想要的(对吗?):
\b(http|www)\.[^\s]+
现在,它只会与http.
和www.
匹配,因此您需要告诉您接受的其他字符:
\b(http|www)\.[^\s\w]+
或
\b(http|www)\.[^\sa-zA-Z]+
所以现在你说,
http
或www
a-z
或A-Z
,不允许任何空格字符注意 - 我没有测试过这些,但希望它们是正确的。
除了(我对它的看法) - \s
表示'空白'。 \b
表示'字边界'。 []
表示“允许的字符范围”。 ^
表示“不是”。 +
表示“一个或多个”。
所以,当你说[^\b]+
时,你说'不允许这个字符范围内的字边界,并且必须有一个或多个',因为那里没有别的&gt;什么都不允许&gt;没有一个或多个&gt;它可能会破裂。
答案 3 :(得分:0)
你应该尝试这样的事情:
\b(http|www).?[\w\.\/]+