JavaScript通过RegExp类型来支持正则表达式。语法:
var exepression = /pattern/flags;
其中,pattern可以任意的正则表达式,可以包含字符类、限定符、分组、向前查找以及反向引用。每一个正则表达式都可带一个或多个标志,用于标明正则表达式的行为。
- g:表示全局模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即停止
- i:表示不区分大小写模式,即在匹配项时忽略模式与字符串的大小写
- m:表示多行模式,即到达一行文本末尾时还会继续查找下一行是否存在匹配项
举例:
// 匹配字符串中所有“at”的实例 var pattern1 = /at/g; // 匹配第一个“bat”或“cat”,不区分大小写 var pattern2 = /[bc]at/i; // 匹配所有以“at”结尾的3个字符的组合,不区分大小写 var pattern3 = /.at/gi;
上面的例子中用到的“[”、“]”、“.”是元字符(类似于编程语言的保留字,使用的时候需要进行转义)。
// 匹配第一个“[bc]at”,不区分大小写 var pattern2 = /\[bc\]at/i; // 匹配所有“.at”,不区分大小写 var pattern4 = /\.at/gi;
另一种创建正则表达式的方式是构造函数:
var exepression = new RegExp("pattern", "flags");
构造函数的第一个参数是字符串形式的模式,在默写情况下需要对字符进行双重转义。所有元字符都必须双重转义,已经转义过的字符也是如此,例如,\n(字符\在字符串中通常被转义为\,而在正则表达式字符串中就会变成\\)。
使用正则表达式字面量和使用RegExp构造函数创建的正则表达式不一样。
var re = null, i; for (i = 0;i < 10; i++) { re = /cat/g; re.test("catastrophe"); } for (i = 0; i < 10; i++) { re = new RegExp("cat", "g"); re.test("catastrophe"); }
在第一个循环中,只为/cat/创建了一个RegExp实例,由于实例属性不会重置,所以在循环中再次调用test()会失败,因为第二次调用时从索引为3的字符("cat"后面的“a”)开始。
第二个循环使用RegExp构造函数,在每次循环中都会创建正则表达式。因此每次迭代都会创建一个新的RegExp实例,所以每次调用test()都会返回true。
实例属性
RegExp的每个实例都具有下列属性,通过这些属性可以获取模式的各种信息。
- global:布尔值,表示是否设置了g标志。
- ignoreCase:布尔值,表示是否设置了i标志
- lastIndex:整数,表示开始搜索下一个匹配项的字符起始位置,从0开始
- multiline:布尔值,表示是否设置了m标志
- source:正则表达式的字符串表示,按照字面量形式而非传入构造函数中的字符串模式返回
var pattern = /[bc]at/i; alert(pattern.global); // false alert(pattern.ignoreCase); // true alert(pattern.multiline); // false alert(pattern.lastIndex); // 0 alert(pattern.source); // "/[bc]at"
实例方法
exec()方法
exec()接收一个参数,即要应用模式的的字符串,返回包含第一个匹配项信息的数组,如果没有匹配项就返回null。返回的数组虽然是Array的实例,但是包含两个额外的属性:
- index:表示匹配项在字符串中的位置
- input:表示应用正则表达式的字符串
在数组中,第一项是与整合模式匹配的字符串,其他项是与模式中的捕获组匹配的字符串(如果模式中没有捕获组,则该数组值包含一项。)
var text = "mom and dad and baby"; var pattern = /mom( and dad( and baby)?)?/gi; var matchers = pattern.exec(text); alert(matchers.index); alert(matchers.index); // "mom and dad and baby" alert(matchers[0]); // "mom and dad and baby" alert(matchers[1]); // " and dad and baby" alert(matchers[2]); // " and baby"
对于exec()方法而言,即使在模式中设置了全局标志,它每次也只会返回一个匹配项。在不设置全局标志的情况下,在同一个字符串上多次调用exec()将始终匹配第一个匹配项的信息。而在设置全局标志的情况下,每次调用exec()都会在字符串中继续查找新匹配项:
var text = "cat, bat, sat, fat"; var pattern1 = /.at/; var matches = pattern1.exec(text); alert(matches.index); // 0 alert(matches[0]); // cat alert(pattern1.lastIndex); // 0 matches = pattern1.exec(text); alert(matches.index); // 0 alert(matches[0]); // cat alert(pattern1.lastIndex); // 0 var pattern2 = /.at/g; var matches = pattern2.exec(text); alert(matches.index); // 0 alert(matches[0]); // cat alert(pattern2.lastIndex); // 3 matches = pattern2.exec(text); alert(matches.index); // 5 alert(matches[0]); // bat alert(pattern2.lastIndex); // 8
在第一个非全局模式下,每次返回第一个匹配项;而在第二个全局模式下,每次返回字符串中的下一个匹配项。在全局模式下,lastIndex的值在每次调用exec()后都会增加,而在全局模式下则不会变。
test()方法
test()方法接收一个字符串参数。在模式与参数匹配的情况下返回true;否则,返回false。
var text = "000-00-000"; var pattern = /\d{3}-\d{2}-\d{3}/; if (pattern.test(text)) { alert("匹配成功"); }
RegExp实例继承的toLocaleString()和toString()方法都会返回正则表达式的字面量,与创建正则表达式的方式无关。
var pattern = new RegExp("\\[bc\\]at", "gi"); alert(pattern.toString()); // /\[bc\]at/gi alert(pattern.toLocaleString()); // /\[bc\]at/gi
RegExp构造函数属性
RegExp构造函数包含一些属性(Opera不支持),这些属性可以作用于作用域中的所有正则表达式,这些属性分别有长属性名和短属性名两种访问方式。
长属性名 | 短属性名 | 说明 |
input | $_ | 最近一次要匹配的字符串 |
lastMatch | $& | 最近一次的匹配项 |
lastParent | $+ | 最近一次的捕获组 |
rightContext | $* | 最近一次的捕获组 |
rightContext | $‘ | Input字符串中lastMatch之后的文本 |
使用这些属性可以从exec()或test()执行的操作中提取更具体的信息。下面通过长属性名访问:
var text = "what are you doing now"; var pattern = /(.)ng/g; if (pattern.test(text)) { alert(RegExp.input); // what are you doing now alert(RegExp.leftContext); // what are you do alert(RegExp.rightContext); // now alert(RegExp.lastMatch); // ing alert(RegExp.lastParen); // i alert(pattern.multiline); // false }
下面通过短属性名访问:
var text = "what are you doing now"; var pattern = /(.)ng/g; if (pattern.test(text)) { alert(RegExp.$_); // what are you doing now alert(RegExp["$`"]); // what are you do alert(RegExp["$‘"]); // now alert(RegExp["$&"]); // ing alert(RegExp["$+"]); // i }
除了上面的属性外,还有9个用于存储捕获组的构造函数属性:RegExp.$1...RegExp.$9,分别存储第一...第九个匹配的捕获组。
var text = "what are you doing now"; var pattern = /(..)in(.)/g; if (pattern.test(text)) { alert(RegExp.$1); // do alert(RegExp.$2); // g }
模式的局限性
JavaScript正则表达式不支持的特性:
- 匹配字符串开始和结尾的\A和\Z锚
- 向后查找
- 并集和交集类
- 原子组
- Unicode支持
- 命名的捕获组
- s(single,单行)和x(free-spacing,无间隔)匹配模式
- 条件匹配
- 正则表达式注释