javascript系列之 正则表达式(规则) 篇
今天我们来聊聊正则表达式的匹配规则,会从修饰符、元字符、量词、贪婪与非贪婪、括号、字符集、反向引用这几方面来了解掌握正则表达式
1.正则表达式的修饰符(可组合使用)
i(ignoreCase) 忽略大小写g(global) 全局匹配,匹配全部符合条件的子串
var str = "BBQ"
var reg1 = /b/
str.replace(reg1, 'a') // BBQ
//大小写不匹配,所以没替换为 'a'
var reg2 = /b/i
str.replace(reg2, 'a') // aBQ
//添加了 i 修饰符,忽略大小写,将第一个 'B' 换为 'a'
var reg3 = /b/ig
str.replace(reg3, 'a') // aaQ
//添加了 ig 修饰符,将全部的 'B' 或 'b' 替换为 'a'
m(multiLine) 多行匹配m修饰符的作用一般是用来修改^和$在正则表达式的作用,让他们分别表示为行首和行尾
var str = "Go\nBBQ"
var reg1 = /^B/
reg1.exec(str) // null
//匹配失败,开头不是 'B' 字符
var reg2 = /^B/m
reg2.exec(str) // ['B', index: 3, input: 'GoBBQ', groups: undefined]
//加了 m 修饰符后,^ 表示行首,因此可以匹配到第二行的 'B'
2.元字符
是拥有特殊含义的字符
| 元字符 | 功能 | 等同于 |
|---|---|---|
| . | 非空格和换行 | [^\n\r] |
| \w | 单词字符 | [0-9A-z_] |
| \W | 非单词字符 | [^\w] |
| \d | 数字字符 | [0-9] |
| \D | 非数字字符 | [^\d] |
| \b | 单词边界 | |
| \B | 非单词边界 |
其中我们就来看看单词边界,即不相邻的两个单词首尾为单词边界,开头和结尾也算边界,如 "hello world"就为"边界hello边界world边界"。
var str = "hello world"
var reg1 = /\bh/
reg1.exec(str)
// ["h", index: 0, input: "hello world", groups: undefined]
var reg2 = /\bw/
reg2.exec(str)
// ["w", index: 6, input: "hello world", groups: undefined]
var reg3 = /d\b/
reg3.exec(str)
// ["d", index: 10, input: "hello world", groups: undefined]
3.量词
| 量词 | 功能 | 等同于 |
|---|---|---|
| n+ | 大于等于1个n字符(>=1) | n{1,} |
| n* | >=0 | n{0,} |
| n? | 0或1个n字符 | {0,1} |
| n{X} | X个n字符 | |
| n{X,Y} | 大于等于X小于等于Y个n字符 | |
| n{X,} | 大于等于X个n字符 | |
| ^n | 开头为n字符 | |
| n$ | 结尾为n字符 |
注意,n{X,Y} 中的 , 和 Y之间不能有空格
4.字符集合 [abc0-9]
格式:[范围]
表示范围内的任意一个字符
如 [abc0-9] 表示 a 或 b 或 c 或 0~9
var str = "3km"
var reg = /^[abc0-9]/
reg.exec(str)
// ["3", index: 0, input: "3km", groups: undefined]
5.反字符集合 [^123]
在正则表达式开始部分的 ^ 表示开头 而在字符集合里面的 ^ 表示非
var str = "3km"
var reg = /^[^123]/ //匹配开头字符,非123的
reg.exec(str) // null
//str 以 3开头,不符合,所以匹配失败
6.贪婪与非贪婪
- 贪婪模式
人都是贪婪的,正则也是如此,如在上面的量词区间中,正则会贪婪的匹配尽可能多的字符
var str = "aaaaac";
var reg = /a{2,5}/
reg.exec(str)
// ['aaaaa', index: 0, input: 'aaaaac', groups: undefined]
正则能够匹配5个时就不会只匹配2个,这就是贪婪模式
- 非贪婪模式
如果我们希望正则尽可能少的去匹配字符,我们需要在后面加上一个 ? ,形式为 {m,n}? +? *? ??
var str = "aaaaac";
var reg = /a{2,5}?/
reg.exec(str)
// ['aa', index: 0, input: 'aaaaac', groups: undefined]
由于开启了非贪婪模式,正则只匹配了2个'a',而不是5个了
7.括号(子正则表达式)
正则表达式内括号里的内容会被认为是子正则表达式,匹配的结果会被记录下来
var str = "hello world"
var reg1 = /(h|b).+/
var result = reg1.exec(str)
// ["hello world", "h", index: 0, input: "hello world", groups: undefined]
其中 result[1] 中的 "h" ,即为子正则表达式匹配的内容
8.不记录子正则表达式的匹配结果
格式:(?:pattern)
不记录的子正则表达式不能被反向引用
var str = "hello world"
var reg1 = /(?:h|b).+/
var result = reg1.exec(str)
// ["hello world", index: 0, input: "hello world", groups: undefined]
可见(?:pattern)不会保存括号内的匹配结果
9.反向引用
格式:(子正则表达式)\num
前面说过子正则表达式匹配的结果会被保存下来,我们可以通过 \ 加 num 的方式来引用第 num 个括号匹配的内容
var str = "aabb"
var reg = /(\w)\1(\w)\2/
reg.exec(str)
// ["aabb", "a", "b", index: 0, input: "aabb", groups: undefined]
第一个括号匹配的内容为 'a',所以 \1 引用为 'a' 第二个括号匹配的内容为 'b',所以 \2 引用为 'b' 所以'aabb'可以被匹配到
10.正向预查
- 格式:
(?=pattern)要匹配的内容,后面必须跟着pattern 但匹配的内容不包括pattern,只是检查后面是否跟着pattern
var str1 = "aabb1"
var str2 = "aabb2"
var reg = /aabb(?=1)/
reg.exec(str1) // ["aabb", index: 0, input: "aabb1", groups: undefined]
reg.exec(str2) // null
(?!pattern)与(?=pattern)相反,后面不能紧跟着pattern