我想了解正则表达式。我一点一点地理解它,但我完全不理解这一点。它基本上是完全合格域名的正则表达式,但要求是结尾不能是.arpa。
(?=^.{4,253}$)(^([a-zA-Z0-9]{1,63}\.)+[a-zA-Z]{2,63}[^.arpa]$)
https://regex101.com/r/hU6tP0/3
这与google.uk不匹配。 如果我把它改为
(?=^.{4,253}$)(^([a-zA-Z0-9]{1,63}\.)+[a-zA-Z]{1,63}[^.arpa]$)
再次有效。
但这也适用
(?=^.{4,253}$)(^([a-zA-Z0-9]{1,63}\.)+[a-zA-Z]{2,63}$)
我想知道为什么:
这是
的思考过程?=^.{4,253}$)(^([a-zA-Z0-9]{1,63}\.)+[a-zA-Z]{2,63}[^.arpa]$)
我认为这是
(?=
是一个积极向前看(有人可以向我解释这实际意味着什么)正如我现在所理解的那样它只是意味着字符串需要匹配正则表达式
^.{4,253}$)
匹配所有字符,但长度必须介于4到253个字符之间。
(^([a-zA-Z0-9]{1,63}\.)
启动捕获组并在其中创建另一个捕获组。这个捕获组说每个非特殊字符可写1到63次或直到。是写的。
+
以前的捕获组可以无限期重复。但它应该总是以一个结束。这样就可以启动下一个捕获组。
[a-zA-Z]{2,63}
然后根据需要多次编写带上部的z,但需要介于2到63之间
[^.arpa]$)
最后一个字符不能是.arpa
有人能告诉我哪里出错了。
编辑:这两个答案都值得一试。
答案 0 :(得分:3)
这不符合你的想法:
[^.arpa]
所有这一切都是'结尾的东西不是字母apr.
' - 它是一个否定的字符类。
您可能会想到negative lookahead assertion:
(?!\.arpa)$
但如果你试图在正则表达式中复合多个标准,我建议你可能正在使用错误的工具来完成工作。由于贪婪/非贪婪的匹配等,它最终变得复杂且难以调试。
你的'正面/负面'前瞻是为了匹配一块未被其他图案包围的图案。但是如果你匹配变量宽度,那可能会有一些意想不到的结果,因为正则表达式引擎会回溯,直到找到匹配的某事。
一个更简单的例子:
([\瓦特] +)(?ARPA)$
适用于:
www.test.arpa
会匹配吗?小组里有什么?
...它会匹配,因为[\w\.]+
将消耗所有这些,然后前瞻不会“看到”任何东西。
如果您使用:
([\w]+)\.(?!arpa)
相反,你会捕捉...... www
,但你不会匹配test
(例如g标志,因为{{1} }之后没有www
,但.arpa
没有。{/ p>
test
因此,在模式中使用否定断言确实变得复杂。我建议不要这样做,并应用两个单独的测试。你很难弄明白,对未来的维护程序员来说也很难!
答案 1 :(得分:2)
这是对你的正则表达式的分析:
(?=^.{4,253}$) # force min length: 4 chars, max length: 253 chars
( # Capturing Group 1 (CG1) - not needed
^ # Match start of the string
( # CG2 (can be a non capturing group '(?:...)')
[a-zA-Z0-9]{1,63} # any sequence of letters and numbers with length between 1 and 63
\. # a literal dot
)+ # CLOSE CG2
[a-zA-Z]{1,63} # any letter sequence with length between 1 to 63
[^.arpa] # a negated char class: any char that is not a "literal" '.','a','r','p' (last 'a' is redundant)
$ # end of the string
) # CLOSE CG1
要避免字符串的尾部为.arpa
,您需要使用否定前瞻(?!...)
,因此请按以下方式进行修改:
(?=^.{4,253}$)(?!.*\.arpa$)(^([a-zA-Z0-9]{1,63}\.)+[a-zA-Z]{2,63}$)
更新:
我升级了正则表达式以使其合理化(我已经将Sobrique建议添加到了一个重要的细节中):
/^(?=.{4,253}$)([a-z0-9]{1,63}[.])+(?!arpa$)[a-z]{2,63}$/i
<强>勒亘强>
/ # js regex delimiter
^ # start of the string
(?=.{4,253}$) # force min length: 4 chars, max length: 253 chars
(?: # Non capturing group 1 (NCG1)
[a-z0-9]{1,63} # any letter or digit in a sequence with length from 1 to 63 chars
[.] # a literal dot '.' (more readable than \.)
)+ # CLOSE NCG1 - repeat its content one or more time
(?!arpa$) # force that after the last literal dot '.' the string does not end with 'arpa' (i've added '$' to Sobrique suggestion instead it prevents also '.arpanet' too)
[a-z]{2,63} # a sequence of letters with length from 2 to 63
$ # end of the string
/i # Close the regex delimiter and add case insensitive flag [a-z] match also [A-Z] and viceversa
var re = /^(?=.{4,253}$)([a-z0-9]{1,63}[.])+(?!arpa$)[a-z]{2,63}$/i;
var tests = ['google.uk','domain.arpa','domain.arpa2','another.domain.arpa.net','domain.arpanet'];
var m;
while(t = tests.pop()) {
document.getElementById("r").innerHTML += '"' + t + '"<br/>';
document.getElementById("r").innerHTML += 'Valid domain? ' + ( (t.match(re)) ? '<font color="green">YES</font>' : '<font color="red">NO</font>') + '<br/><br/>';
}
<div id="r"/>