作为一名编码经验有限的设计师,我一直认为正则表达式是某种黑魔法。最近,我一直在阅读 - 我对它的可能性非常感兴趣。所以我决定在我目前的php项目中首次尝试。
我想找到以下结构的所有网址:
http://[any subdomain, only a-z].domain.com/[any subfolder, can contain a-z,A-Z,0-9,- and _]/
示例:
我的正则表达式:
http://[a-z]*\.domain\.com/[A-Za-z0-9\_\-]*/
我的问题:
(i?)
添加case insencitive,但无法使其正常工作。$ref = preg_replace('"http://[a-z]*\.domain\.com/[A-Za-z0-9\_\-]*/"','',$ref);
答案 0 :(得分:3)
在php中,正则表达式必须由/
分隔,但它几乎可以是任何字符。
您的第二次尝试有效的原因是您使用"
作为分隔符。
要区分大小写,您必须将标记i
放在第二个分隔符之后:
$ref = preg_replace('"http://[a-z]*\.domain\.com/[A-Za-z0-9\_\-]*/"i','',$ref);
here ___^
使用i
标记,不需要[a-zA-Z]
和[a-z]
就足够了。此外,如果它位于字符类中的第一个或最后一个位置,则不需要转义字符类中的下划线_
而不需要转义符号-
$ref = preg_replace('"http://[a-z]*\.domain\.com/[a-z0-9_-]*/"i','',$ref);
请注意,[a-zA-Z0-9_]
可以缩写为\w
,然后您的代码可能如下所示:
$ref = preg_replace('"http://[a-z]*\.domain\.com/[\w-]*/"i','',$ref);
考虑到*
代表0次或更多次,因此您的正则表达式将匹配以下内容:
http://.domain.com//
将*
更改为+
,这意味着一次或多次确保子域至少有一个字符,子文件夹有一个字符:
$ref = preg_replace('"http://[a-z]+\.domain\.com/[\w-]+/"i','',$ref);
然后"
对于分隔符不常见,例如使用#
,~
或!
:
$ref = preg_replace('#http://[a-z]+\.domain\.com/[\w-]+/#i','',$ref);
答案 1 :(得分:3)
以相反的顺序回答您的问题。
如果我在表达式的开头和结尾添加双引号,我只能在php中使用它,为什么会这样? $ ref = preg_replace('http:// [az] .domain.com / [A-Za-z0-9 _-] /“','',$ ref);
您的双引号充当正则表达式分隔符。通常情况下,正斜杠会扮演这个角色,使用它们实际上要求你像对待点一样逃脱它们。几乎任何标点符号都可以作为您的分隔符,因此以下内容都是等效的:
$pattern0 = '"http://[a-z]*\.domain\.com/[A-Za-z0-9\_\-]*/"';
$pattern1 = '!http://[a-z]*\.domain\.com/[A-Za-z0-9\_\-]*/!';
$pattern2 = '/http:\/\/[a-z]*\.domain\.com\/[A-Za-z0-9\_\-]*\//';
这些都是完全有效的,但如果!
不清楚,则惯例是使用/
作为分隔符。我将在下一个问题中坚持使用$pattern1
。
正则表达式正在运行,但我只是想知道它是否可以改进。例如,我尝试使用(i?)添加case insencitive,但无法使其工作。
在最终的正则表达式分隔符之后添加i
以防止不区分大小写:
'!http://[a-z]*\.domain\.com/[A-Za-z0-9\_\-]*/!i'
将连字符-
移动到角色范围的开头,这样你就不会逃脱它。此外,没有必要逃避下划线:
'!http://[a-z]*\.domain\.com/[-A-Za-z0-9_]*/!i'
接下来,使用字符类来简化字符范围。在这种情况下,\w
与[a-zA-Z0-9_]
匹配。
'!http://[a-z]*\.domain\.com/[-\w]*/!i'
最后,您使用*
作为量词意味着您可能会获得一些奇怪的,最终无效的匹配。所有这些都匹配:
http://www.domain.com/foo/
http://.domain.com/foo/
http://.domain.com//
最后两个被打破了。如果您正在解析已知的好URL(例如来自日志文件),那不是真正的问题。如果您需要更严格,请使用+
量词来要求子域和路径中至少有一个字符:
'!http://[a-z]+\.domain\.com/[-\w]+/!i'
现在有点可读了。
答案 2 :(得分:1)
如果您在HTTP之后有[a-z]*\.
,那么这将匹配http://.domain.com/etc/
,这是无效的。我建议改为
http://([a-z]+\.)?domain\.com/[A-Za-z0-9\_\-]*/
这将匹配http://domain.com/etc/
和http://www.domain.com/etc/
,但不匹配http://.domain.com/etc/
。
如果您必须拥有子域名,我建议使用http://[a-z]+\.domain\.com/[A-Za-z0-9\_\-]*/
,这会强制子域名存在。
与最后一组相似。目前它将允许http://www.domain.com//
。我建议使用+
代替*
强制存在目录名称,即[A-Za-z0-9\_\-]+
答案 3 :(得分:1)
之前的 M42 提供了一个很好的答案。我只想补充两点:
所以模式会是这样的:
$pattern = '/https?\:\/\/[a-z]+\.domain\.com\/[a-z0-9\_\-]*\/?/i';
答案 4 :(得分:0)