js-正则表达式
参考-《js高级程序设计第三版》
1 基础概念
正则语法: let expression = /pattern/flags;
pattent: 正则规则
flags: 标志
// 匹配字符串中所有'ab'实例 let pattern1 = /ab/g;
1.1 标志(flags):每个正则表达式可以带一个或多个标志,标明正则表达式的行为,正则表达式的匹配模式支持以下3个标志
g: 表示全局模式,匹配字符串所有的字符
i: 不区分大小写
m: 表示多行,在到达一行文本末尾时还会继续查找下一行是否存在与模式匹配的项
1.2 [] 方括号用于查找某个范围内的字符
表达式 | 描述 |
---|---|
[abc] | 查找方括号之间的任何字符。 |
[^abc] | 查找任何不在方括号之间的字符。 |
[0-9] | 查找任何从 0 至 9 的数字。 |
[a-z] | 查找任何从小写 a 到小写 z 的字符。 |
[A-Z] | 查找任何从大写 A 到大写 Z 的字符。 |
[A-z] | 查找任何从大写 A 到小写 z 的字符。 |
[adgk] | 查找给定集合内的任何字符。 |
[^adgk] | 查找给定集合外的任何字符。 |
(red|blue|green) | 查找任何指定的选项。 |
1.3 正则表达式中使用的元字符必须转义--元字符在正在表达式中都有一种或多种特殊的用途,如果再匹配字符串中包含这些字符,必须转义。正则中的元字符串包括:
() [] {} \ ^ $ | ? * + .
// 匹配第一个‘bat’或‘cat’,不区分大小写 let pattern2 = /[bc]at/i; // 匹配所有已'at'结尾的3个字符串组合,不区分大小写 let pattern3 = /.at/gi; //匹配第一个'[bc]at',不区分大小写 let pattern4 = /\[bc]at/i; //匹配所有以'.at',不区分大小写 let pattern5 = /\.at/gi;
元字符 | 描述 |
---|---|
. | 查找单个字符,除了换行和行结束符。 |
\w | 查找单词字符。 |
\W | 查找非单词字符。 |
\d | 查找数字。 |
\D | 查找非数字字符。 |
\s | 查找空白字符。 |
\S | 查找非空白字符。 |
\b | 匹配单词边界。 |
\B | 匹配非单词边界。 |
\0 | 查找 NUL 字符。 |
\n | 查找换行符。 |
\f | 查找换页符。 |
\r | 查找回车符。 |
\t | 查找制表符。 |
\v | 查找垂直制表符。 |
\xxx | 查找以八进制数 xxx 规定的字符。 |
\xdd | 查找以十六进制数 dd 规定的字符。 |
\uxxxx | 查找以十六进制数 xxxx 规定的 Unicode 字符。 |
1.4 量词
量词 | 描述 |
---|---|
n+ | 匹配任何包含至少一个 n 的字符串。 |
n* | 匹配任何包含零个或多个 n 的字符串。 |
n? | 匹配任何包含零个或一个 n 的字符串。 |
n{X} | 匹配包含 X 个 n 的序列的字符串。 |
n{X,Y} | 匹配包含 X 至 Y 个 n 的序列的字符串。 |
n{X,} | 匹配包含至少 X 个 n 的序列的字符串。 |
n$ | 匹配任何结尾为 n 的字符串。 |
^n | 匹配任何开头为 n 的字符串。 |
?=n | 匹配任何其后紧接指定字符串 n 的字符串。 |
?!n | 匹配任何其后没有紧接指定字符串 n 的字符串。 |
1.5 所有正则表达式都有两种方式创建:
1.字面量形式来定义的正则表达式;
2. 使用RegExp构造函数定义正则表达式
RegExp构造函数接收两个参数:参数1: 匹配的字符串模式, 参数2: flags的字符串形式
// 匹配第一个‘bat’或‘cat’,不区分大小写 let pattern2 = /[bc]at/i; // 与pattern2 相同,RegExp构造函数创建正则表达式 let re1 = new RegExp('[bc]at', 'i');
注意: 传递给构造函数的两个参数都是字符串,在某些情况下要对字符串进行双重转义。所有元字符都必须双重转义,那些转义过得字符也是如此,例如
\n (字符\在字符串中通常被转义为\\, 而在正则表达式字符串中就会变成\\\\)
如下对比
字面量模式 newRegExp等价的字符串 效果
/\[bc\]at/ '\\[bc\\]at' 匹配 '[bc]at'
/\.at/ '\\.at' 匹配 '.at'
/name\/age/ 'name\\/age' 匹配 'name/age'
/\d.\d{1,2}/ '\\d.\\d{1,2}' 匹配 '数字.数字(一个数字或两个数字)'
/\w\\hello\\123/ '\\w\\\\hello\\\\123' 匹配 '单词\hello\123'
1.6 RegExp实例属性(flags)
属性 | 描述 | FF | IE |
---|---|---|---|
global | RegExp 对象是否具有标志 g。 | 1 | 4 |
ignoreCase | RegExp 对象是否具有标志 i。 | 1 | 4 |
lastIndex | 一个整数,标示开始下一次匹配的字符位置,从0算起。 | 1 | 4 |
multiline | RegExp 对象是否具有标志 m。 | 1 | 4 |
source | 正则表达式的源文本。 | 1 | 4 |
2 支持正则表达式的strgin对象的方法
2.1、search()
该方法是最简单的方法了,它以正则表达式为参数,返回第一个与之匹配的子串的开始字符的位置,如果没有任何匹配的话,返回-1。匹配返回1
如果search的参数不是正则的话,它会首先被转成正则。其次,search是不支持全局检索的,所以大家就不要白费力气用它搜全局了--即使用g无效
'abc'.search(/b/i);
2.2 replace()
该方法执行检索与替换操作。第一个参数还是正则表达式,第二个参数是要替换的字符串或者操作函数。当第二个参数是处理函数时,处理函数对应参数分别为当前匹配的子符串、捕获分组、下标、字符串副本
'abc'.replace(/b/gi, '2'); // 'a2c' 'abc'.replace(/(b)/gi, '$1,'); // ‘ab,c’ var str = 'abc12345'; str.replace(/a(b)c1(\d)3/g, function (val, $1, $2, idx, s) { console.log(val, $1, $2, idx, s); // abc123 b 2 0 abc12345 });
2.3、match()
这个方法可以说是String中比较常用的方法,它唯一的参数就是正则表达式,返回的是包含匹配结果的数组。该方法支持全局匹配。
'1a 2b 3c'.match(/(\d)[A-Z]+/gi); '1a 2b 3c'.match(/(\d)[A-Z]+/i); var arr = '1a 2b 3c'.match(/(\d)[A-Z]+/i); console.log(arr, arr.index, arr.input); // ["1a", "1", index: 0, input: "1a 2b 3c"], 0, '1a 2b 3c'
如果有g标识,返回就是包含所有匹配的数组,这时捕获分组是无效的;反之,没有g标识时,返回还是一个数组,数组[0]是完整匹配,数组[n]是$n的捕获(前提是你有捕获分组)。当没有g标识时,返回的匹配数组还会有2个额外属性—index和input,index不用多说了匹配位置,input就是目标字符串的副本
2.4、split()
该方法有2个参数,第二个参数是限制数组的长度,如果指定了,超过这个长度的元素就不会再放进数组里了。
'a,b/c'.split(/[,/]/); // ['a', 'b', 'c']
'a,b/c'.split(/[,/]/, 1); // ['a']
3 ExpReg方法
用RegExp构造正则表达式比直接用正则表达式直接量的优势就在于可以动态地创建一个正则表达式
3.1、exec()
RegExp对象的主要方法,专门用来捕获数组
返回结果为一个Array数组但是包含两个额外的属性 input和index
index: 匹配项在字符传中的位置
input: 应用正则表达式的字符串
该方法和String方法match()很相似,只不过它是以字符串为参数。如果没有匹配到,它将返回null。反之将返回一个数组。
这里的数组具体内容和非全局的match匹配一样。数组[0]是匹配到字符串,数组[n]是对应捕获分组。而且index和input也和match一致。
PS:无论正则表达式是否具有g标示,exec返回的数组类型都是一样的,但是它会把lastIndex属性设置到紧接匹配子串的字符位置,以便下次继续匹配,因为这点特殊性,exec可以遍历调用。
var reg = /abc/g; var str = 'abc,abc'; var result; var sign = 0; while((result = reg.exec(str)) != null) { console.log(result[0], result.index, result.input, reg.lastIndex); if (sign == 0) { sign = 1; reg.lastIndex = 0; } }
3.2、test()
这个方法较简单,就一个参数,如果匹配上了,就返回true,反之为false。它也支持遍历,就相当于调用exec返回值不是null,它就返回true。
PS:这个要小心一个坑,如果你用这2个方法匹配多个字符串,而每次匹配一个字符串又没有匹配完时,lastIndex属性不会自己重置为0的。下面是例子。
var reg = /abc/g; var str = 'abc,12abc'; var result; result = reg.exec(str); console.log(result[0], result.index, result.input, reg.lastIndex); str = 'abc,345abc'; result = reg.exec(str); console.log(result[0], result.index, result.input, reg.lastIndex);
3.3、compile()
可用于改变和重新编译正则表达式。当在循环中有重复正则匹配的时候,用编译后的正则表达式执行起来,效率更高(前提是正则表达式是固定的,如果你每次循环都需要动态适配新正则的话,是没有效果的)。