正则expression式中方括号和括号之间的区别是什么?
以下是我在JavaScript中创build的一个正则expression式:
var reg_num = /^(7|8|9)\d{9}$/
这是我的团队成员提出的另一个build议。
var reg_num = /^[7|8|9][\d]{9}$/
规则是validation电话号码:
- 它应该只有十个数字。
- 第一个数字应该是7,8或9中的任何一个。
这些正则expression式是相当的(为了匹配的目的):
-
/^(7|8|9)\d{9}$/
-
/^[789]\d{9}$/
-
/^[7-9]\d{9}$/
解释:
-
(a|b|c)
是一个正则expression式“OR”,意思是“a或b或c”,尽pipeOR所需的括号的存在也会捕获该数字。 要严格等价,你可以编码(?:7|8|9)
,使其成为非捕获组。 -
[abc]
是一个“字符类”,意思是“来自a,b或c的任何字符”(字符类可以使用范围,例如[ad]
=[abcd]
)
这些正则expression式类似的原因是一个字符类是一个“或”的简写(但只适用于单个字符)。 在另一种情况下,你也可以做一些类似(abc|def)
东西,它不会翻译成字符类。
除了他犯的错误,你的团队的build议几乎是正确的。 一旦你找出原因,你将永远不会忘记它。 看看这个错误。
/^(7|8|9)\d{9}$/
这是什么:
-
^
和$
表示锚定匹配,它声明这些锚点之间的子模式是整个匹配。 如果子模式匹配它的全部,而不仅仅是一个部分,string将只匹配。 -
()
表示一个捕获组 。 -
7|8|9
表示匹配7
或9
任意一个。 它通过交替来完成 ,这就是pipe道运算符|
做 – 交替之间交替。 这在交替之间回溯:如果第一次交替不匹配,则在交替匹配期间引擎位置移动之前引擎必须返回,以继续匹配下一次交替; 而angular色类可以顺序推进。 在优化禁用的正则expression式引擎上查看匹配:
Pattern: (r|f)at Match string: carat
Pattern: [rf]at Match string: carat
-
\d{9}
匹配九位数字。\d
是一个简短的元字符,它匹配任何数字。
/^[7|8|9][\d]{9}$/
看看它做了什么:
-
^
和$
表示锚定的匹配。 -
[7|8|9]
是一个angular色类 。 列表7
任何字符,|
,8
,|
,或者9
可以匹配,从而|
被错误地添加了。 这匹配没有回溯。 -
[\d]
是一个居住在元字符\d
的字符类。 结合使用字符类和单个元字符是一个坏主意,顺便说一下,因为抽象层可能会减慢匹配速度,但这只是一个实现细节,只适用于一些正则expression式实现。 JavaScript是不是一个,但它确实使子模式稍长。 -
{9}
表示先前的单个构造总共重复九次。
最佳正则expression式是/^[789]\d{9}$/
/^(7|8|9)\d{9}$/
/^[789]\d{9}$/
,因为这会在大多数正则expression式实现中导致性能下降( JavaScript正好是一,考虑到在代码中使用关键字var
,这可能是JavaScript)。 使用在PCRE上运行的preg匹配的PHP会优化掉backtracking的缺失,但是我们也不在PHP中,所以使用classes []
而不是replace|
因为匹配不会回溯,因此两者匹配并且失败的速度比使用先前的正则expression式更快。
前两个例子的行为是非常不同的,如果你正在取代他们的东西。 如果你匹配这个:
str = str.replace(/^(7|8|9)/ig,'');
你会用空stringreplace7或8或9。
如果你匹配这个
str = str.replace(/^[7|8|9]/ig,'');
你会取代7
或8
或9
或垂直栏! 由空string。
我刚刚发现了这个困难的方式。