我正在尝试匹配URL的部分。首先,我试图得到一个匹配只有这样的东西:
http://Stackoverflow.com/questions/blah/balh.blah
http://www.stackoverflow.com/questions/blah/balh.blah
stackoverflow.com/questions/blah/balh.blah
www.stackoverflow.com/
但我想使用其他协议,如https
和ftp
以及。我自己写了这样的东西,一点也不好:
((http:'/'/|https:'/'/|ftp:'/'/)*)((www.)*)([a-z]+).([a-z]{2,3})('/)*
这个正则表达式有很多问题,我需要弄清楚如何修复它。
首先,我如何指定例如只有http
或https
有效,而不是htttp
或hazzzzt
或其他?
更准确地说:
- 我们如何指定一个特定的词被包括或排除?
现在很清楚的是,(http)
不被视为一个单词,它只是一个字符的类集,所以任何只有这些字母中的一个的单词都得到匹配。我读过关于'b
作为单词边界的文章,但似乎'bhttp'b
实际上并不意味着将http
视为单个单词而不是一组字符!
对于www
部分,匹配wwww
和ww
或任何其他数量的w
s!无论我输入什么,我总是得到匹配!我使用http://regex101.com/来测试正则表达式。
侯赛因,你的问题有几个要点和问题。
。如何包括或排除一些特定的模式在正则表达式?
有很多技巧。对于简单的模式,您可以指定您想要的,或者指定您不想要的,或者使用负字符类或负查找。对于更复杂的模式,最好从匹配(或替换)模式开始,除了s1、s2、s3等情况
B。如何包含或排除特定的单词?
一般来说,为了确定一个特定的单词属于或不属于一个字符串,如果你不知道它的位置,你在字符串的开头做一个提前查找(或负提前查找):
^(?=.*?MyWord) # makes sure the word is there
或
^(?!.*?MyWord) # makes sure the word is not there
C。What is clear now, is that (http) is not treated like a word, it is just a class set of characters, so any word that has only one of those letters gets a match
这是不对的。(http)
只匹配http
。例如,它将不匹配ptth
。也许您正在考虑[http]
,这将是一个字符类,允许字符h, t和p匹配一次(并且效率低下,因为[pth]
会这样做)
D。如何匹配URL的各个部分
有很多解决方案,但今天我建议不要重新发明轮子。我可以建议使用RegexBuddy库中的正则表达式来实现这个目的吗?这是(?i)'b((?#protocol)https?|ftp)://((?#domain)[-A-Z0-9.]+)((?#file)/[-A-Z0-9+&@#/%=~_|!:,.;]*)?((?#parameters)'?[A-Z0-9+&@#/%=~_|!:,.;]*)?
下面是逐个标记的解释(我在开头添加了不区分大小写的(?i)
修饰符)
- 断言在字边界处的位置(位置之前或之后-但不是同时-由Unicode字母,数字或下划线)
'b
- 匹配下面的正则表达式并将其匹配捕获到反向引用编号1
((?#protocol)https?|ftp)
- 匹配这个选项(只有当这个选项失败时才尝试下一个选项)
(?#protocol)https?
- 注释:协议
(?#protocol)
- 逐字匹配字符串" http "(不区分大小写)
http
- 匹配字符"s"(不区分大小写)
s?
- 在0到1次之间,尽可能多的次数,根据需要回馈(贪婪)
?
- 在0到1次之间,尽可能多的次数,根据需要回馈(贪婪)
- 注释:协议
- 或者匹配此选项(如果此选项不匹配,则整个组失败)
ftp
- 逐字匹配字符串" ftp "(不区分大小写)
ftp
- 逐字匹配字符串" ftp "(不区分大小写)
- 匹配这个选项(只有当这个选项失败时才尝试下一个选项)
- 匹配字符串"://"字面意思
://
- 匹配下面的正则表达式并将其匹配捕获到反向引用号2
((?#domain)[-A-Z0-9.]+)
中- 注释:域
(?#domain)
- 匹配
[-A-Z0-9.]+
下面列表中的单个字符- 在一次到无限次之间,尽可能多的次数,根据需要回馈(贪婪)
+
- 文字字符" - "
-
- 在" A "到" Z "之间的字符(不区分大小写)
A-Z
- 0 ~ 9之间的字符
0-9
- 文字字符"。"
.
- 在一次到无限次之间,尽可能多的次数,根据需要回馈(贪婪)
- 注释:域
- 匹配下面的正则表达式并将其匹配捕获到反向引用编号3
((?#file)/[-A-Z0-9+&@#/%=~_|!:,.;]*)?
- 在0到1次之间,尽可能多的次数,根据需要回馈(贪婪)
?
注释:文件
(?#file)
- 在0到1次之间,尽可能多的次数,根据需要回馈(贪婪)
- 匹配字符"/"
/
- 匹配
[-A-Z0-9+&@#/%=~_|!:,.;]*
下面列表中的单个字符- 在0到无限次之间,尽可能多的次数,根据需要回馈(贪婪)
*
- 文字字符" - "
-
- 在" A "到" Z "之间的字符(不区分大小写)
A-Z
- 0 ~ 9之间的字符
0-9
- +和单个字符从列表中" ;@#/%=~_|!:,.;"
+&@#/%=~_|!:,.;
- 在0到无限次之间,尽可能多的次数,根据需要回馈(贪婪)
((?#parameters)'?[A-Z0-9+&@#/%=~_|!:,.;]*)?
- 在0到1次之间,尽可能多的次数,根据需要回馈(贪婪)
?
- 注释:参数
(?#parameters)
- 匹配字符"?"
'?
- 匹配
[A-Z0-9+&@#/%=~_|!:,.;]*
下面列表中的单个字符- 在0到无限次之间,尽可能多的次数,根据需要回馈(贪婪)
*
- 在" A "到" Z "之间的字符(不区分大小写)
A-Z
- 0 ~ 9之间的字符
0-9
- +和单个字符从列表中" ;@#/%=~_|!:,.;"
+&@#/%=~_|!:,.;
- 在0到无限次之间,尽可能多的次数,根据需要回馈(贪婪)
不认为你需要外部括号,例如下面是匹配http://或www。(确保转义句点)
(http:'/'/|www'.)
如果你使用preg_match和apache。htaccess有一点不同比如你使用一个字符来表示模式的开始和结束比如#
$regEx = '#(http:'/'/|www'.)#';
也许你可以使用PHP过滤器函数?
if (filter_var($url, FILTER_VALIDATE_URL) !== false)
FILTER_VALIDATE_URL根据RFC 2396验证url。
http://www.php.net/manual/de/filter.filters.validate.php