ES5中,RegExp构造函数的两种情况
-
第一种情况是,参数是字符串,第二个参数表示正则表达式的修饰符:
var reg=new RegExp('abc','i'); //i修饰符表示忽略大小写,还有g修饰符,表示全局匹配,m修饰符表示多行匹配 //等价于 var reg=/abc/i;
-
第二种是,参数是一个正则表达式,这时会返回一个原有正则表达式的拷贝:
var reg=new RegExp(/abc/i); //依然等价于 var reg=/abc/i; //但在ES5中,这种方式不允许第二个参数添加修饰符,否则就会报错 var reg=new RegExp(/abc/,'i'); ==>TypeError //这种限制在ES6中得到了修正 RegExp(/abc/ig, 'i').flags ==>i //在ES6中,这种写法不会报错,会改变正则表达式的修饰符,用后写入的i代替原有的ig修饰符 //同时声明,flags是ES6新增的属性,会返回正则表达式的修饰符
正则表达式中的修饰符
-
u修饰符(Unicode模式):
-
用于正确处理大于\uFFFF的Unicode字符用于正确处理大于\uFFFF的Unicode字符
/^\uD83D/u.test('\uD83D\uDC2A') // false /^\uD83D/.test('\uD83D\uDC2A') // true
-
ES6新增了使用大括号表示Unicode,这种正则表达式必须加上u修饰符,才能识别当中的大括号,否则会被解读为量词
/\u{61}/.test('a') ==>false//正则表达式无法识别\u{61}这种表示法,只会认为匹配61个连续的u ,具体原因请查看正则表达式基本语法 /\u{61}/u.test('a') ==>true
-
-
y修饰符(粘连修饰符)
-
与g修饰符类似,都是全局匹配,后一次匹配从上一次匹配成功的位置开始.不同之处在于,g修饰符只要剩余位置中存在匹配即可,而y修饰符必须从剩余的的第一个位置开始,也就是所谓的"粘连".下面通过一个例子更好的理解一下
var s='aaa_aa_a'; var r1=/a+/g; var r2=/a+/y; r1.exec(s) ==>["aaa"] //exec用于返回符合条件的字符串 r2.exec(s) ==>["aaa"] //这里再次调用exec r1.exec(s) ==>["aa"] r2.exec(s) ==>null //解释如下: 首先,r1和r2第一次调用exec匹配,都是从字符串头部开始,因此都能正确匹配到aaa 第二次调用exec,r1和r2就有了区别,r1使用的是g修饰符,它在匹配aaa之后会直接从后面整个内容中寻找符合条件的字符,经过_后匹配到aa返回 而r2使用的y修饰符需要从第一次匹配成功后剩余的第一个位置开始匹配,不能跳过,因此第一次匹配后字符串剩余为'_aa_a',第一个位置为_, 因此匹配不成功,不过跳过_去查找接下来的字符串,直接返回null
-
在split方法中使用y修饰符,原字符串必须以分隔符开头.也就是说,只要匹配成功,数组的第一个成员必定是空字符串
//先说一下split函数,通过括号内的条件切割字符串,不会显示条件包含的字符 'x##'.split(/#/y) ==>['x##'] //从首位置开始查找,第一个字符为x,不匹配,直接将整个字符串返回 '##x'.split(/#/y) ==>['','','x'] //首位置开始查找,匹配成功,切割,返回一个空字符串'',之后同理. //当然,这种方式后续分隔符必须紧跟前面才会被识别 '#x#'.split(/#/y) ==>['','x#']
-
与y修饰符相匹配,ES6的正则对象多了sticky属性,表示是否设置了y修饰符,具体不作演示,正则表达式调用即可
-
-
s修饰符(dotAll模式)
- 正则表达式中
.
修饰符可以代表任意的单个字符,但是行终止符除外:/foo.bar/.test('foo\nbar')
这段代码中,.
修饰符无法正确匹配换行符\n,返回false - 为了解决这个问题,ES6中引入了s修饰符,使得
.
操作符可以真正的p匹配任意单个字符:/foo.bar/s.test('foo\nbar')
这时就可以正确返回true
- 正则表达式中
先行断言和后行断言
-
先行断言:x只有在y前面才能匹配,必须写成
/x(?=y)/
,例如:/\d+(?=%)/.exec('100% of US presidents have been male') // ["100"]
表示返回%前面的数字 -
后行断言:正好相反,x只有在y后面才能匹配,格式为
(?<=y)x
//使用后行断言进行字符串替换 const reg = /(?<=\$)foo/g; '$foo %foo foo'.replace(reg, 'bar'); ==>'$bar %foo foo' //可以看到上述字符串只替换了在$后面的foo
具名组匹配(使用圆括号()
进行组匹配)
-
普通组匹配:
const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/; const matchObj = RE_DATE.exec('2019-03-06'); const year = matchObj[1]; ==> 2019 const month = matchObj[2]; ==> 03 const day = matchObj[3]; ==> 06 //上面代码中,正则表达式里有三组圆括号,使用exec方法就可以将这三组匹配结果提取出来,类似于数组的各部分 //这样的形式虽然也可以,但是每一组的具体含义不得而知,而且如果组的顺序改变的话,引用的时候就必须修改序号,因此会引入具名组匹配
-
具名组匹配:
const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/; const matchObj = RE_DATE.exec('1999-12-31'); const year = matchObj.groups.year; // 1999 const month = matchObj.groups.month; // 12 const day = matchObj.groups.day; // 31 //可以看到两者的区别就是具名组匹配通过?<name>添加了具体的组名,这样就可以通过具体的组名来调用了,而且无需在意顺序问题,而且使用序号调用依然有效 //如果没有可以匹配的组名,则返回undefined
关于正则表达式的问题,大致就这么多,还有一些基础的零散的知识没有具体列出来,希望对大家有帮助
网友评论