我一直在寻找一个正则表达式来替换字符串中的纯文本url(字符串可以包含多个url),方法是:
<a href="url">url</a>我发现了这个:http://mathiasbynens.be/demo/url-regex
我想使用diegoperini的regex (根据测试是最好的):
_^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS但我想让它全局替换字符串中的所有url。当我使用这个的时候:
/_(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?_iuS/g它不工作,我如何使这个正则表达式是全局的,开头的下划线和结尾的"_iuS“是什么意思?
我想在php中使用它,所以我使用:
preg_replace($regex, '<a href="$0">$0</a>', $examplestring);发布于 2012-09-10 21:43:17
下划线是正则表达式分隔符,i、u和S是模式修饰符:
I (PCRE_CASELESS)
如果设置了此修饰符,则模式中的字母将同时匹配大小写字母。
U (PCRE_UNGREEDY)
这个修饰符颠倒了量词的“贪婪”,因此它们在缺省情况下不是贪婪的,但如果后面跟着?,它们就会变得贪婪。它与Perl不兼容。它也可以通过模式中的(?U)修饰符设置或通过量词后面的问号(例如.*?)来设置。
S
当一个模式要被多次使用时,值得花更多的时间来分析它,以加快匹配所需的时间。如果设置了此修饰符,则会执行此额外分析。目前,学习模式只对没有单个固定起始字符的非锚定模式有用。
有关更多信息,请参阅http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php
当您添加/ ... /g时,您添加了另一个正则表达式分隔符加上修饰符g,这就是它不起作用的原因。
发布于 2013-01-19 09:33:38
我同意@verdesmarald,并在以下函数中使用了此模式:
$string = preg_replace_callback(
"_(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?_iuS",
create_function('$match','
$m = trim(strtolower($match[0]));
$m = str_replace("http://", "", $m);
$m = str_replace("https://", "", $m);
$m = str_replace("ftp://", "", $m);
$m = str_replace("www.", "", $m);
if (strlen($m) > 25)
{
$m = substr($m, 0, 25) . "...";
}
return "<a href=\"$match[0]\">$m</a>";
'), $string);
return $string;它似乎起到了作用,并解决了我遇到的一个问题。正如@verdesmarald所说,删除^和$字符使模式即使在我的pre_replace_callback()中也可以工作。
我唯一关心的是模式的效率有多高。如果在繁忙/高流量的web应用中使用,会不会造成瓶颈?
更新
如果在url的路径部分的末尾有一个尾迹点,那么上面的正则表达式模式就会中断,比如http://www.mydomain.com/page.。为了解决这个问题,我修改了正则表达式模式的最后部分,添加了^.,使最后部分看起来像[^\s^.]。在我读它的时候,不要匹配尾随的空格或点。
到目前为止,在我的测试中,它似乎工作得很好。
https://stackoverflow.com/questions/12352635
复制相似问题