JavaScript正则表达式的模式匹配
正则表达式(regular expression)是一个描述字符模式的对象。JavaScript的RegExp表示正则表达式,String和RegExp都定义了方法,后者使用正则进行强大的模式匹配和文本检索与替换功能。JavaScript的正则表达式语法是Perl5的正则表达式语法的大型子集,所以对于有Perl编程经验人来说,学习JavaScript的正则表达式是很简单的。
正则表达式的定义
JavaScript中正则表达式用RegExp对象表示,可以使用RegExp()构造函数来创建RegExp对象。不过RegExp对象更多的是通过一种特殊的直接量语法来创建。
就像通过引号包裹字符的方式来定义字符串直接量一样,正则表达式直接量定义为包含在一对斜杠(/)之间的字符。
例如:var pattern = /s$/;
RegExp直接量和对象的创建
就像字符串和数字一样,程序中每个取值相同的原始类型直接量均表示相同的值,这是显而易见的。程序运行每次遇到对象直接量(初始化表达式)诸如{}和[]的时候都会创建新对象。比如,若果在循环体中写var a=[],则每次遍历都会创建一个新的空数组。
正则表达式直接量则与此不同,ECMS3规范规定,一个正则表达式直接量会在执行到它时转换一个未RegExp对象,同一段代码所表示正则表达式直接量的每次运算都返回同一个对象。ECMS5规范则做了相反的规定,同一段代码所表示的正则表达式直接量的每次运算都返回新对象。IE一直都是按照ECMS5规范实现的,多数最新版本的浏览器也开始遵循ECMS5,尽管目前该标准并未全面广泛推行。
直接量字符
正则表达式中的所有字母和数字都是按照字面含义进行匹配的。JS正则表达式语法也支持非字母字符匹配,这些字符需要通过反斜杠()作为前缀进行转义。
字符 匹配
字母和数字字符 本身
\o NUL字符(\u0000)
\n 换行符(\u000A)
\t 制表符(\u0009)
\v 垂直制表符(\u00B)
\f 换页符(\u000C)
\r 回车符(\u000D)
\xnn 由十六进制nn指定的拉丁字符如\xOA=\n
\uxxx 由十六进制指定Unicode字符,如\u0009=\t
\cX 控制字符^X,例如,\cJ=换行符\n
在正则表达式中,许多标点符号具有特殊含义,它们是:
^ $ . * + ? = ! : | \ / ( ) [ ] { }
如果想在正则表达式中使用这些字符的直接量进行匹配,则必须使用前缀\,这是一条通行规则。 如果不记得哪些标点符号需要反斜线转义,可以在每个标点符号前都加上反斜杠。另外,需要注意,许多字母和数字在有反斜线做前缀是也有特殊含义,所以对于想按照直接量进行匹配反斜线本身,则必须使用反斜线来将其转义。
字符类
将直接量字符单独放进方括号内就组成了字符类。一个字符类可以匹配它所有包含的任意字符。正则表达式/[abc]/就和字母”a”、”b”、”c”中任意一个都匹配,另外,通过”^”来定义否定字符类,它匹配所有不包含在方括号内的字符。
正则表达式字符类
字符 匹配
[…] 方括号内的任意字符
[^…] 不在方括号内的任意字符
. 除换行符和
\w 任何ASCEII字符组成的单词等价于[a-zA-Z0-9]
\W 任何不是ASCII字符组成的单词,等价于[^a-Za-z-0-9]
\s 任何Unicode空白符
\S 任何非Unicode空白符的字符,注意\W和\S不同
\d 任何ASCII数字,等价于[0-9]
\D 除了ASCII数字之外的任何字符,等价于[^0-9]
[\b] 退格直接量(特例)
注意,在方括号之内也可以写这些特殊转义字符,比如\s匹配所有的空白字符,\d匹配所有的数字,因此/[\s\d]/就匹配任意空白字符或者数字。
重复
可以把两位数描述成/\d\d/,四位数描述成/\d\d\d\d/。我们在正则模式之后跟随用以指定字符重复的标记。 正则表达式的重复字符语法
字符 含义
{n,m} 匹配前一项至少n次,但不能超过m次
{n,} 匹配前一项n次或者更多次
{n} 匹配前一项n次
? 匹配前一项0次或者1次,也就是说前一项是可选的,等价于{0,1}
+ 匹配钱一项一次或多次,等价于{1,}
* 匹配前一项0次或多次,等价于{01}
例子:
/\d{2,4}/ //匹配2~4个数字
/\w{3}\d?/ //精确匹配三个单词和一个可选的数字
/\s+java\s+/ //匹配前后带有一个或者多个空格的字符串”java”
/[^(]*/ //匹配一个或者多个非左括号的字符
非贪婪的重复
上面列出的匹配重复字符是尽可能多地匹配,而且允许后续的正则表达式继续匹配。因此,我们称之为”贪婪的”匹配。
我们同样可以使用正则表达式进行非贪婪匹配。 只需在待匹配的字符后面跟随一个问号即可:”??”、”?+”、”*?”或”{1,5}?”。比如,正则表达式/a+/可以匹配一个或多个连续的字母a。
选择、分组和引用
正则表达式的语法还包括指定选择项、子表达式分组和引用前一子表达式的特殊字符。字符” | ”用于分隔供选择的字符。 |
字符 含义
| 选择,匹配的是该符号左边的子表达式或右边的子表达式
(…) 组合,将几个项组合为一个单元,这个单元可通过”*”、”+”、”?”和”|”等等符号加以修饰,
而且可以记住和这个组合匹配的字符串以供此后的引用使用
(?:…) 只组合,把项组合到一个单元,但不记忆与该组合相匹配的字符
\n 和第n个分组第一次匹配的字符相匹配,组是圆括号中的子表达式(也有可能是嵌套的),
组索引是从左到右的左括号数,”(?:”形式的分组不编码
指定匹配位置
正如前面所介绍的,正则表达式中的多个元素才能够匹配字符串的一个字符。例如,\s匹配的只是一个空白符。
正则表达式中的锚字符
字符 含义
^ 匹配字符串的开头,在多行检索中,匹配一行的开头
$ 匹配字符串的结尾,在多行检索中,匹配一行的结尾
\b 匹配一个单词的边界,简言之,就是位于字符\w和\W之间的位置,
或位于字符\w和字符串的结尾或开头之间的位置(但需要注意,[\b]匹配的是退格符)
\B 匹配非单词边界的位置
(?=p) 零宽正向先行断言,要求接下来的字符都与p匹配,但不能包括匹配p的那些字符
(?!p) 零宽负向先行断言,要求接下来的字符不与p匹配
修饰符
正则表达式中的语法还有最后一个知识点,即正则表达式的修饰符,用以说明高级匹配模式的规则。
字符 含义
i 执行不区分大小写的匹配
g 执行一个全局匹配,简言之,即找到所有的匹配,而不是在找到第一个之后就停止
m 多行匹配模式,^匹配一行的开头和字符串的开头,$匹配行的结束和字符串的结束
RegExp对象
正则表达式是通过RegExp对象来表示的。除了RegExp()构造函数之外,RegExp对象还支持三个方法和一些属性。接下来的两节会对RegEep模式匹配方法和属性展开讲述。
//全局匹配字符串中的5个数字,注意这里使用了”\”,而不是”\”
var zipcode =new RegExp(“\\d{5}”,”g”);
RegExp的属性
每个RegExp对象都包含5个属性。属性source是一个只读的字符串,包含正则表达式的文本。属性global是一个只读的布尔值,用以说明这个正则表达式是否带有修饰符g。
RegExp的方法
RegExp对象定义了两个用于执行模式匹配操作的方法。它们的行为和上文介绍过的String方法很类似。
RegExp最主要的执行模式匹配的方法是exec(),它与10.2节介绍过的String方法match()相似,只是RegExp方法的参数是一个字符串,而String方法的参数是一个RegExp对象。
exec()方法对一个指定的字符串执行一个正则表达式,简言之,就是在一个字符串中执行匹配检索。