ES5 正则表达式
1.两种语法
1 | var patt = new RegExp('abc','g') |
查找 abc,其中的 g 是修饰符,表示全局的
其中的 i 是修饰符,表示不区分大小写
注意:当使用构造函数创造正则对象时,需要常规的字符转义规则(在前面加反斜杠 \)。比如,以下是等价的:
1 | var patt = /abc/g |
意思和上边相同
2.三种方法
test() //返回 true 或者 false
exec() //返回的是数值,是数组,重复数值只显示一次
match() //返回的是数值,是数组,重复数值显示多次
exec 和 match 区别
var reg = /abc/g
var str = “1abc2,3abc4”
console.log(reg.exec(str)) //返回 abc 只匹配一个
console.log(str.match(reg)) //返回 abc,abc 匹配多个
reg.test(str)
补:
replace()
search()
split()
3.常用元字符
. 匹配除换行符以外的其他字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意的空白字符
\d 匹配数字
\b 匹配单词的开始或结束
\n 匹配新行
\r 匹配行首
^ 匹配字符串的开始
\$ 匹配字符串的结束
备注:
1 | 如果文本不存在换行符,那么.和[\b\B]和[\d\D]和[\s\S]和[\w\W]是等价的。 |
4.字符转义
在前边加\
一般.和*还有()都需要
5.限定符-重复
* 重复 0 次或更多次
+ 重复 1 次或更多次
? 重复 0 次或 1 次
{n} 重复 n 次
{n,} 重复 n 或更多次
{n,m}重复 n 到 m 次
6.字符类-查找字符集合
[] 匹配[]内的元素,字符之前是或的关系,返回也是一个字符而不是一个单词
例:
[.?!] 匹配.或?或!
[a-z] 匹配 a 到 z 之间的数任意一个字符
[A-Z] 匹配 A 到 Z
[0-9] 匹配 0 到 9
7.分支条件-类似于或的关系
| 两种规则可以通过|来实现或的关系
8.分组-就是上边的重复,只是对象不是单字符了
() 被括起来的进行分组
例:
(\d{1,3}){3} 表示一个 1 到 3 位的数字,重复三遍–就是三个三位数字
9.反义–和元字符意思相反
\W 匹配任意不是字母,数字,下划线,汉字
\S 匹配任意不是空白符的字符
\D 匹配任意不是数字的字符
\B 匹配任意不是单词的开始或结束位置
[\^x] 匹配任意除了 x 以外的任意字符
[\^aeiou] 匹配除了 aeiou 以外的任意字符
10 分组的两种形式
捕获组和非捕获组
10.1 捕获组
10.1.1 向后引用–取到匹配值返回数组
(exp) 和分组很像,都是用括号括起来,但是这里返回的是查到符合 exp 的数组,而分组不反回数组
1 | '<App>hello regex</App><p>A</p><p>hello regex</p>'.match(/<((A|a)pp)>(hello regex)+<\/\1><p>\2<\/p><p>\3<\/p>/); |
10.1.2 捕获命名
(?
1 | '<App>hello regex</App>'.match(/<(?<tag>[a-zA-Z]+)>.*<\/\k<tag>>/); |
在捕获组内部最前面加上?
10.2 非捕获组
(?:exp) 捕获符合 exp 的元素,不捕获匹配的文本 会省一些系统资源
1 | // 捕获组 |
11.零宽断言–一般就是只查到这个词之后向前找或者向后找
零宽(zero-width)是什么意思?指的就是它匹配一个位置,本身没有宽度。
断言(assertion)是什么意思?指的是一种判断,断言之前或之后应该有什么或应该没有什么。
11.1 正向零宽断言
11.1.1 先行断言
(?=exp) 匹配到 exp 的元素,向他前边找要匹配的元素 例:\b\w+(?=ing\b) ing 前边要有字符,且一直向前找到头返回字符串
11.1.2 后行断言
(?<=exp) 匹配到 exp 后边的位置
11.2 负向零宽断言–和反义字符[^x]差不多是一个意思
11.2.1 先行断言
(?!exp) 匹配不包含 exp 规则的字符 例:\b\wq(?!u)\w\b 表示 q 后边是一个非 u 的字符
例子:
1 | const requireAll = requireContext => requireContext.keys().map(requireContext) |
正则表达式中有(?=a)和(?!a)来表示我们是否需要匹配(找到)某个东西。
而上边说的匹配和不匹配是说 match 出来的数组,是两个概念
1 | ^(?!.*hello) |
这里.*用来表示 hello 之前可能有其他的字符,为什么还要加^呢,因为如果不加的话,可能匹配到 h 之后的这个位置上了。
11.2.2 后行断言
(?<!exp) 匹配 exp 前边的位置 (?<![a-z])\d{7}返回七位数字,且他们前边不能是小写字母
12. 贪婪–匹配尽可能多的字符
a.*b 匹配字符串中最长的从 a 到 b 的字符串,可以理解为从第一个 a 开始找,一直找到最后一个 b 结束
13. 懒惰–匹配从第一个字符到最近的结束字符的字符串
*? 重复任意次,但尽可能少重复 例:a.*?b 原式:aabab 匹配到:aab ab
+? 重复 1 次或任意次,但尽可能少重复
?? 重复 n 次或更多次,但尽可能少重复
{n,m}?重复 n 次到 m 次,但尽可能少重复
{n,}? 重复 n 次或更多次,但尽可能少重复
14. 贪婪和懒惰对比讲解
1 | // 贪婪-默认 |
紧跟在?
后面的?它不是一个量词,而是一个模式切换符,从贪婪模式切换到非贪婪模式。
贪婪模式在正则中是默认的模式,就是在既定规则之下匹配尽可能多的文本。
因为正则中有量词,它的重复次数可能是一个区间,这就有了取舍。
紧跟在量词之后加上?就可以开启非贪婪模式。怎么省事怎么来。(上边的例子就是最少可以是 0 次)
这里的要点是,?
必须紧跟着量词(所以不一定是?),否则的话它自己就变成量词了。
ES6 正则表达式
1 字符=2 字节或者 4 字节
1.RegExp 构造函数
1 | var regex = new RegExp(/xyz/, i); //ES5不可以这么声明 |
2.字符串方法:
match()、replace()、search()和 split()
在语言内部全部调用 RegExp 的实例方法,从而做到所有与正则相关的方法,全都定义在 RegExp 对象上。
3.u 修饰符
含义为“Unicode 模式”,用来正确处理大于\uFFFF 的 Unicode 字符。
1 | /^\uD83D/u.test("\uD83D\uDC2A"); |
3.1 点字符
点.字符是除了换行符以外的任意单个字符。对于码点大于 0xFFFF 的 Unicode 字符,点字符不能识别,必须加上 u 修饰符。
1 | var s = '𠮷'; |
3.2 Unicode 字符表示法
使用大括号表示 Unicode 字符,u 修饰符(/后边的那个),才能识别。
1 | /\u{61}/.test("a") / // false 第一个\u仅仅是字符编码的固定格式,没有第二个u的话,这个式子就不是识别4字节的方法,而是普通的两字节 |
3.3 量词
使用 u 修饰符后,所有量词都会正确识别大于码点大于 0xFFFF 的 Unicode 字符。
1 | /𠮷{2}/.test('𠮷𠮷') // false 没有u,还无法识别前边那个𠮷 |
3.4 预定义模式
1 | /^\S$/.test('𠮷') // false 上面代码的\S是预定义模式,匹配所有不是空格的字符,无法识别𠮷 |
3.5 i 修饰符
1 | //\u004B与\u212A都是大写的K,证明\u212A是非规范的 |
4.y 修饰符
除了 u 修饰符,ES6 还为正则表达式添加了 y 修饰符,叫做“粘连”(sticky)修饰符。
y 修饰符的作用与 g 修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始。不同之处在于,g 修饰符只要剩余位置中存在匹配就可,而 y 修饰符确保匹配必须从剩余的第一个位置开始,这也就是“粘连”的涵义。
1 | var s = "aaa_aa_a"; |
使用lastIndex
属性,可以更好地说明 y 修饰符,不包含位置字符
1 | const REGEX = /a/y; |
y 修饰符号隐含了头部匹配的标志 ˆ
在 split 方法里,如果匹配成功意味着第一个成员肯定 split 括号内的参数,参数被替换后变成都逗号,逗号前边就肯定是个空字符了
1 | // 没有找到匹配 |
用途:可以判断是否含有非法字符
1 | const TOKEN_Y = /\s*(\+|[0-9]+)\s*/y; |
5.sticky 属性
判断是否设置了 y 修饰符。
1 | var r = /hello\d/y; |
6.flags 属性
返回正则表达式的修饰符。
1 | // ES5的source属性 |
7.RegExp.escape()
字符串必须转义,才能作为正则模式。
未放入 ES7,所以暂时不讨论
8.后行断言
先行断言指的是,x 只有在 y 前面才匹配,必须写成/x(?=y)/
比如,只匹配百分号之前的数字,要写成/\d+(?=%)/
先行否定断言指的是,x 只有不在 y 前面才匹配,必须写成/x(?!y)/
比如,只匹配不在百分号之前的数字,要写成/\d+(?!%)/。
后行断言正好与”先行断言”相反,x 只有在 y 后面才匹配,必须写成/(?<=y)x/
比如,只匹配美元符号之后的数字,要写成/(?<=\$)\d+/
后行否定断言则与”先行否定断言”相反,x 只有不在 y 后面才匹配,必须写成/(?<!y)x/
比如,只匹配不在美元符号后面的数字,要写成/(?<!\$)\d+/。
参考文献:http://www.jb51.net/tools/zhengze.html
参考文献:https://www.jb51.net/article/52491.htm
参考文献:http://es6.ruanyifeng.com/#docs/regex
一次性搞懂 JavaScript 正则表达式之语法
Whistle 常用
1 | /https:\/\/app.zhuanzhuan.com\/zz\/transfer\/zzfinance\?([^=&]+)=([^&]*)/ http://localhost:3000/$2 resDelay://0000 |