5.1 结构和操作符
而在正则表达式中,操作符都体现在结构中,即由特殊字符和普通字符所代表的一个个特殊整体。
JS正则表达式中,都有哪些结构呢?
- 字符字面量、字符组、量词、锚字符、分组、选择分支、反向引用
具体含义简要回顾如下
- 字面量,匹配一个具体字符,包括不用转义的和需要转义的。比如a匹配字符"a",又比如
\n
匹配换行符,又比如\.
匹配小数点。 - 字符组,匹配一个字符,可以是多种可能之一,比如
[0-9]
,表示匹配一个数字。也有\d
的简写形式。另外还有反义字符组,表示可以是除了特定字符之外任何一个字符,比如[^0-9]
,表示一个非数字字符,也有\D
的简写形式。 - 量词,表示一个字符连续出现,比如
a{1,3}
表示“a”字符连续出现3次。另外还有常见的简写形式,比如a+
表示“a”字符连续出现至少一次。 - 锚点,匹配一个位置,而不是字符。比如^匹配字符串的开头,又比如\b匹配单词边界,又比如
(?=\d)
表示数字前面的位置。 - 分组,用括号表示一个整体,比如
(ab)+
,表示"ab"两个字符连续出现多次,也可以使用非捕获分组(?:ab)+
。 - 分支,多个子表达式多选一,比如
abc|bcd
,表达式匹配"abc"或者"bcd"字符子串。 - 反向引用,比如
\2
,表示引用第2
个分组
其中涉及到的操作符有
- 转义符
\
- 括号和方括号
(...)、(?:...)、(?=...)、(?!...)、[...]
- 量词限定符
{m}
、{m,n}
、{m,}
、?
、*
、+
- 位置和序列
^
、$
、\元字符
、 一般字符 - 管道符(竖杠)
|
上面操作符的优先级从上至下,由高到低
这里,我们来分析一个正则
/ab?(c|de*)+|fg/
- 由于括号的存在,所以,
(c|de*)
是一个整体结构 - 在
(c|de*)
中,注意其中的量词*,因此e*是一个整体结构 - 又因为分支结构
“|”
优先级最低,因此c是一个整体、而de*
是另一个整体 - 同理,整个正则分成了
a、b?、(...)+、f、g
。而由于分支的原因,又可以分成ab?(c|de*)+
和fg
这两部分
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1HScFMyD-1617851248887)(http://7xq6al.com1.z0.glb.clouddn.com/regg.jpeg)]
5.2 注意要点
匹配字符串整体问题
- 因为是要匹配整个字符串,我们经常会在正则前后中加上锚字符^和$
- 比如要匹配目标字符串
"abc"
或者"bcd"
时,如果一不小心,就会写成/^abc|bcd$/
量词连缀问题
假设,要匹配这样的字符串
每个字符为a、b、c任选其一
字符串的长度是3的倍数
- 此时正则不能想当然地写成
/^[abc]{3}+$/
,这样会报错,说+
前面没什么可重复的 - 此时要修改成
/([abc]{3})/
元字符转义问题
- 所谓元字符,就是正则中有特殊含义的字符
- 所有结构里,用到的元字符总结如下
^ $ . * + ? | \ / ( ) [ ] {
} = ! : - ,
当匹配上面的字符本身时,可以一律转义
var string = "^$.*+?|\\/[]{}=!:-,";
var regex = /\^\$\.\*\+\?\|\\\/\[\]\{\}\=\!\:\-\,/;
console.log( regex.test(string) );
// => true
- 其中string中的\字符也要转义的
- 另外,在string中,也可以把每个字符转义,当然,转义后的结果仍是本身
var string = "^$.*+?|\\/[]{}=!:-,";
var string2 = "\^\$\.\*\+\?\|\\\/\[\]\{\}\=\!\:\-\,";
console.log( string == string2 );
// => true
字符组中的元字符
跟字符组相关的元字符有
[]
、^
、-
。因此在会引起歧义的地方进行转义。例如开头的^
必须转义,不然会把整个字符组,看成反义字符组
var string = "^$.*+?|\\/[]{}=!:-,";
var regex = /[\^$.*+?|\\/\[\]{}=!:\-,]/g;
console.log( string.match(regex) );
// => ["^", "$", ".", "*", "+", "?", "|", "\", "/", "[", "]", "{", "}", "=", "!", ":", "-", ","]
5.3 案例分析
身份证
/^(\d{15}|\d{17}[\dxX])$/
因为竖杠“
|
”,的优先级最低,所以正则分成了两部分\d{15}
和\d{17}[\dxX]
\d{15}
表示15
位连续数字\d{17}[\dxX]
表示17
位连续数字,最后一位可以是数字可以大小写字母"x"
IPV4地址
/^((0{0,2}\d|0?\d{2}|1\d{2}|2[0-4]\d|25[0-5])\.){3}(0{0,2}\d|0?\d{2}|1\d{2}|2[0-4]\d|25[0-5])$/
得出如下的结构:
((...)\.){3}(...)
上面的两个(…)是一样的结构。表示匹配的是3位数字。因此整个结构是
3位数.3位数.3位数.3位数
然后再来分析(…)
(0{0,2}\d|0?\d{2}|1\d{2}|2[0-4]\d|25[0-5])(0{0,2}\d|0?\d{2}|1\d{2}|2[0-4]\d|25[0-5])
它是一个多选结构,分成5个部分
0{0,2}\d
,匹配一位数,包括0补齐的。比如,9、09、009;0?\d{2}
,匹配两位数,包括0补齐的,也包括一位数;1\d{2}
,匹配100
到199
;2[0-4]\d
,匹配200-249
;25[0-5]
,匹配250-255
。