JS正则表达式之RegExp构造函数
Updated:
一、 RegExp 类型
ECMAScript通过RegExp类型来支持正则表达式
Perl 语法:
var expression = / pattern / flags;
- pattern(模式) 部分可以是任何简单或复杂的正则表达式,可以包含字符类,限定符,分组,向前查找以及反向引用。
- flags(标志)部分用以标明正则表达式的行为。
正则表达式的匹配模式支持下列三个标志
- g: 表示全局模式(global),即模式将被应用所哟字符串,而非在发现第一个匹配项时立即停止;
- i:表示不区分大小写,即在确定匹配项时忽略模式与字符串的大小写
- m: 表示多行模式,即在到达一行文本末尾时还会继续查找下一行中是否存在与模式匹配的项。
例:匹配所有以 .at 结尾的3个字符的组合,不区分大小写
var pattern = /.at/gi;
注意:模式中使用的所有的元字符都必须转义
正则表达式中的元字符包括:
( [ { \ ^ $ | ) ? * + . ] }
例:匹配第一个“bat” 或 “cat” ,不区分大小写1
var pattern = /[bc]at/i;
例: 匹配第一个“[bc]at”, 不区分大小写1
var pattern = /\[bc\]at/i
可以看出,对[]进行转义。
例:匹配所有已“at”结尾的3个字符的组合,不区分大小写1
var pattern = /.at/gi;
例:匹配所有“.at”,不区分大小写1
var pattren = /\.at/gi;
可以看出,对.进行了转义
二、 使用RegExp构造函数创建正则表达式
RegExp构造函数接收两个参数
- 参一:要匹配的字符串模式
- 参二:可选的标志字符串
例:匹配第一个“bat” 或 “cat” ,不区分大小写1
2var pattern1 = /[bc]at/i
var pattren2 = new RegExp("[bc]at", "i");
两个相同,只不过是使用构造函数创建的。
注意:
- 传递给RegExp构造函数的两个参数都是字符串
- 不能把正则表达式字面量传递给RegExp构造函数
- 由于RegExp构造函数的模式参数是字符串,所以要对字符进行双重转义,所有元字符都必须进行双重转义,那些经过转义的字符也是如此。(例如:
\n
,字符\
在字符串中被转义为\\
,而在正则表达式字符串中就会变成\\\\
)
字面量模式 | 等价的字符串 |
---|---|
/\\bc\]at/ |
"\\[bc\\]at" |
/\.at/ |
"\\.at" |
/name\age/ |
"name\\age" |
/\d.\d{1,2}/ |
"\\d.\\d{1,2}" |
/\w\\hello\\123/ |
"\\w\\\\hello\\\\123" |
注意:ES5中明确规定,使用正则表达式字面量必须像直接调用RegExp构造函数一样,每次地创建新的RegExp实例。
三、 RegExp实例属性
- global:布尔值,表示是否设置了g标志
- ignoreCase: 布尔值,表示是否设置了g标志
- lastIndex:整数,表示开始搜索下一个匹配项的字符位置,从0算起
- multiline:布尔值,表示是否设置了m标志
- soure:正则表达式的字符串表示,按照字面量形式而非传入构造函数中的字符串模式返回
例:可以获知一个正则表达式的各方面信息1
2
3
4
5
6var pattern = /\[bc\]at/i/;
alert(pattern.global); //false;
alert(pattern. ignoreCase); //true;
alert(pattern. multiline); //false;
alert(pattern. lastIndex); //0;
alert(pattern. soure); //"\[bc\]at";
四、 RegExp实例方法
1. exec( )与捕获组
这里我们主要介绍 RegExp对象的主要方法exec( ),需要了解的是这个方法是专门为捕获组设计的。
- exec( )接受一个参数时(即要应用模式的字符串),返回包含第一个匹配项信息的数组
- 包含两个额外的属性
- index:表示匹配文本的第一个字符的位置
- input:表示存放的为被检索 的字符串string、
例:1
2
3
4
5
6
7
8var text = "mom and dad and baby";
var pattern = /mom( and dad (and baby)?)?/gi;
var matches = pattern.exec(text);
alert(matches.index); //0
alert(matches.input); //mom and dad and baby
alert(matches[0]); //mom and dad and baby
alert(matches[1]); //and dad and baby
alert(matches[2]); //and baby
分析:
可以看到正则表达式有用到括号,这里的括号分割了三个捕获组,从外到内(外面表示有一个无形的括号)分别是:
1
2
3mom and dad and baby
and dad and baby
and baby?
表示{0,1}次(这个在上一篇博客里有说到)matches.index 表示要匹配文本的第一个字符的位置,所以返回0
- matches.input 输出被检索的字符串
- matches[0] 表示输出和第一个捕获组相匹配的字符串 ,即 mom and dad and baby
- matches[1] 表示输出和第二个捕获组相匹配的字符串,即 and dad and baby
- matches[2] 表示输出和第三个捕获组相匹配的字符串,即 and baby
2. exec( )与全局标志
- 在模式中设置全局标志 g,每次只会返回一个匹配项
- 不设置全局标志的情况下,多次调用exec( )始终返回第一个匹配项的信息
- 设置全局标志,每次调用exec( )则会在字符串中继续查找新匹配项
看一个小例子:1
2
3
4
5
6
7
8
9
10
11
12var text = 'cat, bat, sat, fat';
var pattern = /.at/;
var matches = pattern.exec(text);
alert(matches.index); //0
alert(matches[0]); //cat
alert(pattern.lastIndex); //0
matches = pattern.exec(text);
alert(matches.index); //0
alert(matches[0]); //cat
alert(pattern.lastIndex); //0
分析:
在模式中没有设置全局标志,所以matches是否为全局,都只会返回一个匹配项1
2
3
4
5
6
7
8
9
10
11
12var text = 'cat, bat, sat, fat';
var pattern = /.at/g;
var matches = pattern.exec(text);
alert(matches.index); //0
alert(matches[0]); //cat
alert(pattern.lastIndex); //3
matches = pattern.exec(text);
alert(matches.index); //5 bat中at所出现的位置+1 (从前往后)
alert(matches[0]); //bat
alert(pattern.lastIndex); //8 bat中at所出现的位置+1(从后往前)
分析:
- 在模式中设置了全局标志,当matches不是全局时,多次调用exec( )始终返回第一个匹配项的信息
- 当matches是全局时,每次调用exec( )则会在字符串中继续查找新匹配项
五、 RegExp构造函数属性
RegExp构造函数包含一些属性,这些属性在其他语言中被看成是静态属性,这些属性适应于作用域中的所有正则表达式,并且基于所执行的最近一次正则表达式操作而变化。
可以通过两种方式来进行访问
RegExp构造函数属性列表
| 长属性名 | 段属性名 | 说明 |
|–|–|–|
| input | $_ | 最近一次要匹配的字符串,Opera未实现此属性|
| lastMatch | $& | 最近一次的匹配项,Opera未实现此属性|
| lastParen | $+ | 最近一次匹配的捕获组,Opera未实现此属性|
| leftContext| $` | input字符串中lastMatch之前的文本,Opera未实现此属性|
| rightContext | $’ | input字符串中lastMatch之后的文本,Opera未实现此属性|
| multiline | $* | 布尔值,表示是否所有表达式都使用多行模式,Opera未实现此属性|
例:匹配任何一个字符后边跟hort1
2
3
4
5
6
7
8
9
10
11var text = 'this has bean a short summer';
var regx = /(.)hort/g;
if(regx.test(text)){
alert(RegExp.input);//this has bean a short summer
alert(RegExp.lastMatch);/ort
alert(RegExp.lastParen);//s
alert(RegExp.leftContext);//this has bean a
alert(RegExp.rightContext);// summer
alert(RegExp.multiline);//undefined
}
分析:
- ()代表一个捕获组,.表示任意一个字符,即将第一个字符放在了一个捕获组中
- input 返回了原始字符串
- leftContext 返回summer之前的字符串
- rightContext 返回summer之后的字符串
- lastMatch 返回最近一次与整个正则表达式匹配的字符串,即summer
- lastParen 返回最近一次的捕获组,即s
- multiline 是RegExp对象的实例所有的属性,并不是RegExp对象所有的,RegExp上没有multiline这个属性,所以返回undefined
当然上面的例子也可以使用短属性名来表示
除了上面介绍的属性,还有多达9个用于存储捕获组的构造函数属性,访问这些属性的语法是:
(RegExp.$1,RegExp.$2,RegExp.$3,RegExp.$4,RegExp.$5,RegExp.$6,RegExp.$7,RegExp.$8,RegExp.$9),一共有9个。官方的解释是,这些可以捕获组的字符串的自动填充。1
2
3
4
5
6var text ="this has bean a short summer";
var pattern =/(..)or(.)/g;
if(pattern.test(text)){
console.log(RegExp.$1);/
console.log(RegExp.$2);//t
}
分析:
- . 表示任意一个字符
- ()括号表示捕获组
- 第一个括号表示第一个捕获组,即or前面的两个字符
- 第二个括号表示第二个捕获组,即or后面的一个字符
如果还是不明白,可以试着分析下面一个例子:1
2
3
4
5
6
7var text ="you are in haorooms";
var pattern =/(.)ao(..)om(.)/g;
if(pattern.test(text)){
console.log(RegExp.$1);//h
console.log(RegExp.$2);//ro
console.log(RegExp.$3);//s
}