本节内容我们继续探讨关于ES2015的一些新的内容,在js中我们经常用一些正则表达式去匹配验证一些表单信息,比如email,url,password格式等等。在ES6版本中,引入了一些新的正则表达式的用法,通过这些方法,允许我们实现一些更灵活的的正则验证, 本节内容的实例代码来源于<You don’t know JS> 系列书籍。
Unicode 标志位
ES6通过引入了一个新的“u”标志位,允许对于Unicode字符串进行匹配,在原来的ES5版本中,正则表达式对于扩展字符集比如中文汉字,认为这是两个字符,所以如果想要匹配到这些扩展集合,必须同时对两个字符进行匹配。引入的“u”标志位,则告诉正则表达式,使用UTF-16的方式去解释字符,这时候对于一个汉字来说,就可以当做是一个字符来处理了。
我们通过一个简单的例子,来看一下js对于字符的处理:
/𝄞/.test( "𝄞-clef" );
true
/^.-clef/.test( "𝄞-clef" );
false
/^.-clef/u.test( "𝄞-clef" );
// true
上述的例子中,“.”代表了除了回车和换行之外的所有字符,如果其中的𝄞是一个字符的话,第二个表达式应该是返回真才对,但实际上他是占据了两个字符,所以无法匹配上,表达式返回假值。当我们设置了u标志位的时候,他就被认为是一个字符处理了,所以最终第三个的表达式为真。
Sticky 粘滞位
ES6中增加的另一个标志位为y,代表了开启一个粘滞模式匹配。通过该方式我们可以设置匹配的精确位置,代码如下:
var a=/hello/
a.lastIndex // 0
a.test("say: hello world") // true
a.lastIndex // 0
var b=/hello/y
b.test("say: hello world") // false
b.lastIndex=5
b.test("say: hello world") // true
b.lastIndex // 10
b.test("say: hello world") // false
b.lastIndex //0
比如我们只想匹配某个字符串从第10个字符开始位置是否是我们需要的字符串,就可以通过手动的指定lastIndex来移动匹配锚。 可见y参数对于那些可被预测匹配位置的,或者固定格式字符串匹配比较高效。
另外一个例子中使用了稍微复杂的正则匹配,先来看下正则表达式:
/\d+\.\s(.*?)(?:\s|$)/
正则表达式如下图所示:
这个表达式中我们\d+代表至少一个数字,.代表匹配一个.符号,\s代表空白符,(.*)代表了匹配任意的字符串,后面跟的?代表了非贪婪捕获,这样我们就会将剩余的字符全部匹配上,(?:)代表了匹配但不捕获,用于返回的结果中不去包含该分组,\s|$ 代表空白或者结束符号
对于非粘滞位的操作如下:
var str = "1. foo 2. bar 3. baz";
var re = /\d+\.\s(.*?)(?:\s|$)/
str.match( re );
// ["1. foo ", "foo"]
str.match( re );
// ["1. foo ", "foo"]
str.match( re );
// ["1. foo ", "foo"]
不管我们匹配多少次结果都是一样的,因为并未移动匹配位置。当我们使用y粘滞位的时候,则结果如下面代码中所示:
var re = /\d+\.\s(.*?)(?:\s|$)/y
str = "1. foo 2. bar 3. baz";
str.match( re );
// ["1. foo ", "foo"]
str.match( re );
// ["2. bar ", "bar"]
str.match( re );
// ["3. baz", "baz"]
当然使用全局/g 也可以实现依次的输入输出,但是可控的匹配位置操作还是增加了很多使用上的灵活性,可以满足一些特殊的匹配需求。
使用注意
在javascript中使用正则表达式的地方很多,比如test(),match(),String.search(),String.split()等等,不同的函数在使用/g与/y时候的行为有所不同,有些函数会在使用/y的时候依照lastIndex位置开始匹配,而有一些则忽略该位置定义,比如search()不管设置lastIndex与否,使用\y时候都从开始位置匹配。具体的可参考链接。使用时多留意。
不错