RegExp 类型是 ECMAScript 支持正则表达式的一个接口,提供了最基本的和一些高级的正则表达式功能。
函数实际上是 Function 类型的实例,因此函数也是对象;而这一点整是 JavaScript 最有特色的地方。由于函数对象,所以函数也拥有方法,可以用来争抢其行为。
因为有了基本包装类型,所以 JavaScript 中的基本类型值可以被当做对象来访问,三种基本包装类型分别是:Boolean、Number和String。
- 每个包装类型都映射到同名的基本类型。
- 在读取模式下访问基本类型值时,就会创建对应的基本包装类型的一个对象,从而方便了数据操作。
- 操作基本类型值的语句一经执行完毕,就会立即销毁新创建的包装对象。
在所有代码执行之前,作用域中就已经存在两个内置对象:Global 和 Math 。在大多数 ECMAScript 实现中都不能直接访问 Global 对象;不过,Web 浏览器实现了承担该角色的 window 对象。全局变量和函数都是 Global 对象的属性。Math 对象提供了很多属性和方法,用于辅助完成复杂的数学计算任务。
创建正则表达式
var expression = / pattern / flags ;
var expression1 = new RegExp('pattern', flags);
使用类似Perl的语法,可以创建一个正则表达式。
其中的模式(pattern)部分可以是任何简单或复杂的正则表达式,可以包含字符类、限定符、分组、向前查找以及反向引用。
- g:表示全局(global)模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即停止;
- i:表示不区分大小写(case-insensitive)模式,即在确定匹配项时忽略模式与字符串的大小写;
- m:表示多行(multiline)模式,即在到达一行文本末尾时还会继续查找下一行中是否存在于模式匹配的项;
与其他语言中的正则表达式类似,模式中使用的所有元字符都必须转义。
/*
正则表达式包括:
( [ { / ^ $ | ? * + . } ] )
这些元字符在正则表达式中都有一或多种特殊用途,因此如果想要匹配字符串中包含的这些字符,就必须对它们进行转义
*/
// 匹配字符串中所有 'at' 的实例
var pattern1 = /at/g;
// 匹配第一个'bat' 或 'cat', 不区分大小写
var pattern2 = /[bc]at/i;
// 匹配第一个'[bc]at', 不区分大小写
var pattern2 = /\[bc\]at/i;
// 匹配所有以 ' at' 结果的3个字符的组合,不区分大小写
var pattern3 = /. at/gi;
// 匹配所有以 '.at',不区分大小写
var pattern3 = /\. at/gi;
字面量模式 | 等价的字符串 |
---|---|
/[bc]at/ | "\\[bc\\]at" |
/.at/ | "\\.at" |
/name/age/ | "name\\/age" |
/\d.\d{1, 2}/ | "\\d.\\d{1, 2}" |
/\w\hello\123/ | "\\w\\\\hello\\\\123" |
字符串
\
在字符串中通常被转义为\\
, 而在正则表达式字符串中就会变成\\\\
。
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");
}
test() 方法用来匹配传入的字符串是否符合正则表达式。
ECMAscript 5 之前 使用字面量不是创建一个新的正则表达式实例,有点像单例模式,会导致循环调用test时失败的情况。
ECMAScript 5 明确规定,使用正则表达式字面量必须像直接调用RegExp构造函数一样,每次都创建新的RegExp示例。IE9、Fiefox 4+、和Chrome都据此做出了修改。
RegExp 实例属性
RegExp 对象的主要方法是 exec(), 该方法是专门为捕获组而设计的。 exec() 接受一个参数,即要应用模式的字符串,然后返回包含第一个匹配项信息的数组;或者在没有匹配项的情况下返回 null。
返回的数组虽然是Array的实例,但包含两个额外的属性:index 和 input。
其中 index 表示匹配项在字符串中的位置,而 input 表示应用正则表达式的字符串。
在数组中,第一项是与整个模式匹配的字符串,其他项是与模式中的捕获组匹配的字符串(如果模式中没有捕获组,则该数组只包含一项)。
Exec
var 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
这个实例中包含两个捕获组 ()
。
最内部的捕获组匹配 "and baby",而包含它的捕获组匹配 "ant dad" 或者 "and dad and baby"。
当把字符串传入 exec() 方法中之后,发现了一个匹配项。
因为整个字符串本身与模式匹配,所以返回的数组 matchs 的 index 属性值为 0。
数组中的第一项是匹配的整个字符串,第二项包含与第一个捕获组匹配的内容,第三项包含与第二个捕获组匹配的内容。
对于 exec() 方法而言,即使在模式中设置了全局标志(g),它每次也只会返回一个匹配项。
在不设置全局标志的情况下,在同一个字符串上多次调用 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
上面例子中 pattern1
不是全局模式,因此每次调用 exec()
返回的都是第一个匹配项 ("cat")
。
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
上面例子中 pattern2
是全局模式,因此每次调用 exec()
都会返回字符串中的下一个匹配项,直至搜索到字符串末尾为止。
注意
lastIndex
的变化,在全局匹配模式下,lastIndex的值在每次调用exec()
后都会增加,而在非全局模式下则始终保持不变。
test
接受一个字符串参数,在模式与该参数匹配的情况下返回
true
,否则返回false
。
在指向知道目标字符串与某个模式是否匹配,但不需要指定其文本内容的情况下,使用这个方法非常方便。
因此,
test()
方法经常被用在id语句中。
var text = "000-00-0000";
var pattern = /\d{3}-\d{2}-\d{4}/;
if (pattern.test(text)) {
alert("匹配成功")
}
RegExp 构造函数属性
RegExp 构造函数包含一些属性(这些属性在其他语言中被看成是静态属性)。
这些属性适用于作用域中的所有正则表达式,并且基于所有执行的最近一次正则表达式操作而变化。
关于这些属性的另一个独特之处,就是可以通过连各种方式访问它们。
这些属性分别有一个长属性名和一个短属性名(Opera是例外,它不支持短属性名)。
长属性名 | 短属性名 | 说明 |
---|---|---|
input | $_ | 最近一次要匹配的字符串(Opera未实现) |
lastMatch | $& | 最近一次的匹配项(Opera未实现) |
lastParen | $+ | 最近一次的匹配的捕获组(Opera未实现) |
lastContext | $ |
input 字符串中 lastMatch 之前的文本 |
multiline | $* | 布尔值,表示是否所有表达式都使用多行模式。(IE和Opera未实现) |
rightContext | $' | Input 字符串中 lastMatch 之后的文本 |
使用这些属性可以从 exec()
或 test()
执行的操作中提取出更具体的信息。
var text = "this has been a short summer";
var pattern = /(.)hort/g;
if (pattern.test(text)) {
alert(RegExp.input); // this has been a short summer
alert(RegExp.leftContext); // this has been a
alert(RegExp.rightContext); // summer
alert(RegExp.lastMatch); // short
alert(RegExp.lastParen); // s
alert(RegExp.multiline); // undefined
}
var text = "this has been a short summer";
var pattern = /(.)hort/g;
if (pattern.test(text)) {
alert(RegExp['$_']); // this has been a short summer
alert(RegExp["$`"]); // this has been a
alert(RegExp["$'"]); // summer
alert(RegExp['$&']); // short
alert(RegExp['$+']); // s
alert(RegExp['$*']); // undefined
}
- input 属性返回了原始字符串。
- leftContext 属性返回了单词 short 之前的字符串。
- rightContext 属性返回了单词 short 之后的字符串。
- lastMatch 属性返回最近一次与整个正则表达式匹配的字符串。
- lastParen 属性返回最近一次匹配的捕获数组,即例子中的
s
。
模式的局限
-
不匹配字符串开始和结尾的 \A 和 \Z 锚
但支持以插入符号
(^)
和美元符号($)
来匹配字符串的开始和结尾。 -
不支持向后查找(lookbehind)
但完全支持向前查找(lookahead)。
不支持原子组(atomic grouping)
不支持Unicode(单个字符除外,如 \uFFFF)
-
不支持命名的捕获组
但支持编号的捕获组
不支持
s(single, 单行)
和x(free-spacing,无间隔)
匹配模式不支持条件匹配
不支持正则表达式注释