2012-03-28 99 views
1

我需要一个函数来检查字符串中的现有URL。正则表达式匹配大多数URL需要改进

function linkcleaner($url) { 
$regex="(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))"; 

if(preg_match($regex, $url, $matches)) { 
echo $matches[0]; 
} 
} 

正则表达式从John Gruber's blog,在那里他讨论创建一个正则表达式匹配的所有URL的问题而采取的。 不幸的是,我不能让它工作。看起来问题来自正则表达式中的双引号或表达式末尾的其他点符号。 任何帮助表示赞赏。 谢谢!

+10

“不能使它工作“不是内置的PHP错误信息。 – 2012-03-28 16:38:25

+2

@JackManey,roflmao – 2012-03-28 16:50:30

+0

对不起,错误是“Parse error:syntax error,unexpected','在C:\ ... \ config.php on line ...”。英语不是我的母语,有时我解释我想说的话有问题。 – olegb3 2012-03-28 17:06:51

回答

2

除了@ tandu的回答,你还需要在php中使用正则表达式的分隔符。

最简单的将是开始和结束与#你的模式,即文字没有出现在它:

$regex="#(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'\".,<>?«»“”‘’]))#"; 
+0

编辑了我的答案,使用'#“可能是url的一部分(指定主播)... – poncha 2012-03-28 17:10:04

+0

谢谢!我怎么会错过那个...救了我的一天:) – olegb3 2012-03-28 17:10:55

+0

@poncha它不会出现在这个正则表达式模式中,那是唯一重要的东西。 – jeroen 2012-03-28 17:16:17

3

你需要躲避"\

1

杰克·梅尼的评论... EPIC:d

在一个更严重的是,这是行不通的,因为你终止在中间的字符串字面权。

要在字符串中的双引号("),您需要使用\

所以逃吧,行会

$regex="/(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'\".,<>?«»“”‘’]))/"; 

通知我躲过了(')以及。这是为了在两个单引号之间定义一个字符串。

+0

谢谢@tandu 我仍然收到一个错误警告:preg_match()[function.preg-match]:未知修饰符'\'在C:\ wamp \ www \ ... \ config.php上919行 – olegb3 2012-03-28 17:01:23

+0

I想想在PHP中,你需要在开始和结束时用相同的字符分隔正则表达式。我使用'/' – 2012-03-29 03:34:29

1

我不知道你们怎么看这个表达式,因为它是一个真正的痛苦读取/修改...;)

试试这个(这不是一个班轮,是的,但很容易理解,如果需要修改):

<?php 
$re_proto = "(?:https?|ftp|gopher|irc|whateverprotoyoulike)://"; 
$re_ipv4_segment = "[12]?[0-9]{1,2}"; 
$re_ipv4 = "(?:{$re_ipv4_segment}[.]){3}".$re_ipv4_segment; 
$re_hostname = "[a-z0-9_]+(?:[.-][a-z0-9_]+){0,}"; 
$re_hostname_fqdn = "[a-z0-9_](?:[a-z0-9_-]*[.][a-z0-9]+){1,}"; 
$re_host = "(?:{$re_ipv4}|{$re_hostname})"; 
$re_host_fqdn = "(?:{$re_ipv4}|{$re_hostname_fqdn})"; 
$re_port = ":[0-9]+"; 
$re_uri = "(?:/[a-z0-9_.%-]*){0,}"; 
$re_querystring = "[?][a-z0-9_.%&=-]*"; 
$re_anchor = "#[a-z0-9_.%-]*"; 
$re_url = "(?:(?:{$re_proto})(?:{$re_host})|{$re_host_fqdn})(?:{$re_port})?(?:{$re_uri})?(?:{$re_querystring})?(?:{$re_anchor})?"; 

$text = <<<TEXT 
http://www.example.com 
http://www.example.com/some/path/to/file.php?f1=v1&f2=v2#foo 
http://localhost.localdomain/ 
http://localhost/docs/??? 
www....wwhat? 
www.example.com 
ftp://ftp.mozilla.org/pub/firefox/latest/ 
Some new Mary-Kate Olsen pictures I found: the splendor of the Steiner Street Picture of href… http://t.co/tJ2NJjnf 
TEXT; 

$count = preg_match_all("\01{$re_url}\01is", $text, $matches); 
var_dump($count); 
var_dump($matches); 
?> 
+0

你的答案是greate!这是唯一正则表达式正确解析以下字符串:'RT @JustBrelieve:“@ enn4xor:#TBT去年夏天。 * _ * http://t.co/LsasKwfe“你可爱,你可爱。' – Oleg 2012-07-26 08:58:08

+0

我发现了一些问题'$ re_hostname_fqdn'参数。它匹配'玛丽 - 凯特'作为URL在'我发现一些新的玛丽 - 凯特奥尔森图片:辉煌的斯坦纳街图片href ... http:// t.co/tJ2NJjnf' – Oleg 2012-07-26 09:12:59

+0

@Oleg'$ re_hostname_fqdn'会匹配'玛丽 - 凯特',因为它是一个可能的主机名(如任何单词......),但它为什么匹配无原型...我会研究这个,感谢注意 – poncha 2012-07-26 10:52:12