JS中的正则表达式
如果对于正则基础没有太多了解的同学可以先看这篇文章:初探正则表达式。
正则表达式是一个描述字符模式的对象,JavaScript
的 RegExp
类表示正则表达式,String
和 RegExp
都定义了方法,后者使用正则表达式进行强大的模式匹配和文本检索于替换功能。JavaScript
的正则表达式语法是 Perl5
的正则表达式语法的子集。
JS中正则表达式的定义
JavaScript 中的正则表达式用RegWxp对象表示,可以使用RegExp()构造函数来创建RegExp对象,不过RegExp对象更多的是通过一种特殊的直接量语法来创建。就像通过引号包裹字符的方式来定义字符串直接量一样,正则表达式直接量定义为包含在一对斜杠(/)之间的字符,比如:
var someReg = /s$/
var someReg2 = new RegExp("s$")
其实,这两个表达式是等价的,都匹配以字母s结尾的字符串,只不过第一个以直接量定义,第二个以正则表达式定义。
js中正则表达式的修饰符
修饰符 | 说明 |
---|---|
i | 执行不区分大小写的匹配 |
g | 执行一个全局匹配,即找到所有匹配而不是找到一个就停止 |
m | 多行匹配模式 ^ 匹配一行的开头和字符串的开头 $ 匹配行的结束和字符串的结束 |
用于匹配模式的String方法
String
支持4种使用正则表达式的方法。
search()
:"JavaScript".search(/script/i);
search()
的参数是一个正则表达式,返回第一个与之匹配的字串的起始位置,如果到不到匹配的字串,它将返回 -1
,如果它的参数不是正则表达式,则首先会通过RegExp构造函数将他转化成正则表达式,它不支持全局搜索,因为它忽略正则表达式中的修饰符 g
。上面的表达式将返回 4
。
replace()
:text.replace(/javascript/gi, "JavaScript");
replace()
用来执行检索和替换操作。其中第一个参数是一个正则表达式,第二个参数是要进行替换操作的字符串。这个方法会对调用它的字符串进行检索,使用指定的模式来匹配。如果 replace()
的第一个参数是一个字符串,那么它将直接搜索这个字符串,而不是和 search()
一样先通过 RegExp()
将它转换成正则表达式。上面的表达式将文本中所有的 javascript
(不区分大小写)统一替换为 JavaScript
。
march()
:"1 and 2 and 3".match(/\d+g);
match()
方法是最常用的String正则表达式方法。它唯一的参数就是一个正则表达式,返回的是一个匹配结果组成的数组。如果该表达式设置了修饰符 g
,则该方法反悔的数组中包括了字符串中所有匹配结果。如果这个这个正则表达式没有设置修饰符 g
,它只检索第一个匹配。但是即使它不是全局匹配,它也返回一个数组,在这种情况下,数组的第一个元素就是匹配的字符串,剩下的元素则是正则表达式中用圆括号扩起来的子表达式。上面代码返回 ["1","2","3"]
split()
:"123,456,789".split(",");
这个方法将调用他的字符串拆分成一个字串组成的数组,使用的分隔符是 split()
的参数,它的参数也可以是一个正则表达式。上面的代码返回 ["123","456","789"]
。
RegExp对象
除了 RegExp()
构造函数以外,RegExp
对象还支持三个方法和一些属性。
RegExp()
构造函数可以有两个字符串参数,第一个参数包含正则表达式的主体部分。需要注意的是不管是字符串直接量还是正则表达式,都是用 \
作为转义字符的前缀,因此当给构造函数传入一个字符串表述的正则表达式时,必须要将 \
替换成 \\
。如果提供第二个参数,它就制定正则表达式的修饰符。
var thisReg = new RegExp("\\d{5}","g");
RegExp的属性
source
: 只读的字符串,包含正则表达式的文本。global
: 只读的布尔值,说明这个正则表达式是否带有修饰符g
。ignoreCase
: 只读的布尔值,说明这个正则表达式是否带有修饰符i
。multiline
: 只读的布尔值,说明这个正则表达式是否带有修饰符m
。lastIndex
: 可读写的整数,如果这个正则表达式带有修饰符g
,这个属性储存在整个字符串中下次检索的开始位置,这个属性会被exec()
和test()
方法用到。
RegExp的方法
RegExp
对象定义了两个用于执行模式匹配操作的方法。
exec()
它与我们之前介绍的 match()
相似,只是它的参数是一个字符串,而 match()
的参数是一个RegExp对象。
exec()
对一个指定的字符串执行匹配检索。如果它没有找点任何匹配,它就返回 null
,但是如果他找到一个匹配,它将返回一个数组,这个数组第一个元素包含的是与正则表达式相匹配的字符串,余下的就是正则表达式括号内的子表达式。
和 match()
不同,不管正则表达式是否具有全局修饰符 g
,exec()
都会返回一样的数组。当调用 exec()
的正则表达式对象具有修饰符 g
的时候,它把当前正则表达式的 lastindex
属性设置为紧挨着匹配字串的字符位置。当同一个字符串第二次调用 exec()
的时候,他将会从 lastIndex
所指示的字符位置开始检索。如果没有任何匹配结果,他将会把 lastIndex
设置为 0
(我们也可以在任何时候进行设置)。
test()
调用 test()
和调用 exec()
等价,当 exec()
的返回结果不是 null
的时候,test()
返回 true
。由于这种等价性,当一个全局表达式调用 test()
时,它的行为和 exec()
一样。
ES6中正则的扩展
RegExp构造函数
在ES5中,RegExp()
只能接受字符串作为参数,ES6允许其直接接受正则表达式作为参数。
let regex = new RegExp(/xyz/i)
字符串的正则方法
ES6中将字符串对象的4个正则方法在语言内部全部调用 RegExp
的实例方法,使得所有与正则有关的方法全部都定义在了 RegExp
对象上。
如 String.prototype.match
调用 RegExp.prototype[Symbol.match]
u修饰符
ES6对正则表达式增加了 u
修饰符,含义为“Unicode模式”,用来正确处理大于 \uFFFF
的Unicode字符。
y修饰符
ES6还为正则表达式添加了 y
修饰符。他的作用和 g
修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一位置开始。不同之处在于,g
修饰符只要剩余位置中存在匹配就行,而 y
修饰符会确保匹配从剩余的第一个位置开始。g
修饰符会忽略非法字符, y
不会。
let s = "aaa_aa_a";
let r1 = /a+/g;
let r2 = /a+/y;
r1.exec(s) // ["aaa"]
r2.exec(s) // ["aaa"]
r1.exec(s) // ["aa"]
r2.exec(s) // null
sticky属性
与 y
修饰符对应,ES6的正则对象对了 sticky
属性,用来表示是否设置了 y
修饰符。
flags属性
ES6为正则表达式新增了 flags
属性,返回正则表达式的修饰符。