1.元字符
这里是正则表达式用到的所有元字符
( [ { \ ^ $ | ) ? * + .
任何时候要在正则表达式中使用这些元字符,都必须对它们进行转义。因此要匹配一个问号,正则表达式就该这样表示:
var veQMark =/\?/;
或者这样表示:
var veQMark=new RegExp("\\?");
注意当正则表达式以第二种形式表示时,所有的反斜杠都必须用两个反斜杠来替换,因为javascript字符串解析器会按照\n的方式尝试翻译\?。为了保证不会出现这个问题,在元字符的前面加上两个反斜杠(双重转义)。这个小小的gotcha就是多数开发者更偏好使用字面量语法的原因。
2.使用特殊字符
要使用ASCII来表示一个字符,则必须指定一个两位的十六进制代码,并有前面加上\x。例如字符b的ASCII码为98,等于十六进制的62,因此,表示字符b可以使用\x62
另外也可以使用八进制代替十六进制来指定字符代码,直接在反斜杠之后跟上八进制数值,例如,b等于八进制的142,所以下面就该这样
/\142/
如果要使用Unicode来表示字符,必须指定字符串的四位十六进制表示形式,因此b应该是\u0062
另外还有其他一些预定义的特殊字符,如下表所列
字符 | 描述 |
\t | 制表符 |
\n | 换行符 |
\r | 回车符 |
\f | 换页符 |
\a | alert字符 |
\e | escape字符 |
\cx | 与X相对应的控制字符 |
\b | 回退字符 |
\v | 垂直制表符 |
\0 | 空字符 |
3.字符类
3.1简单类
假设相匹配"bat","cat","fat"。使用简单类可以很方便的解决这个问题
/[bcf]at/gi
后面的g表示全匹配,i表示不区分大小写。
3.2负向类
要匹配除了a和b的所有字符,那么这个字符就是[^ab]
3.3范围类
[a-z]
[A-Z]
[0-9]
[^1-4]
3.4组合类
匹配所有从a~m的字母以及从1~4的数字,以及一个换行符
[a-m1-4\n]
3.5预定义类
代码 | 等同于 | 匹配 |
. | [^\n\r] | 除了换行和回车之外的任意字符 |
\d | [0-9] | 数字 |
\D | [^0-9] | 非数字字符 |
\s | [\t\n\x0B\f\r] | 空白字符 |
\S | [^\t\n\x0B\f\r] | 非空白字符 |
\w | [a-zA-Z_0-9] | 单词字符(所有字母,所有的数字和下划线) |
\W | [^a-zA-Z_0-9] | 非单词字符 |
4.量词
4.1简单量词
代码 | 描述 |
? | 出现零次或一次 |
* | 出现零次或多次 |
+ | 出现一次或多次(至少出现一次) |
{n} | 一定出现n次 |
{n,m} | 至少出现n次但不超过m次 |
{n,} | 至少出现n次 |
贪婪量词:先看整个的字符串是不是一个匹配,如果没有发现匹配,它去掉字符串中的最后一个字符,并再次尝试。直到发现一个匹配字符或者字符串不剩任何字符。
惰性量词:先看字符串中的第一个字线是不是一个匹配。如果单独这个字符还不够,就读入下一个字符,组成两个字符的字符串,如果还是没有发现匹配,继续添加字会直到发现一个或者整个字符都检查过也没有匹配。其工作方式恰好与贪婪相反。
支配量词:只尝试匹配整个字符串。如果整个字符串不能产生匹配,不做进一步尝试。
表示方法如下表
贪婪 | 惰性 | 支配 | 描述 |
? | ?? | ?+ | 零次或一次出现 |
* | *? | *+ | 零次或多次出现 |
+ | +? | ++ | 一次或多次出现 |
{n} | {n}? | {n}+ | 恰好n次出现 |
{n,m} | {n,m}? | {n,m}+ | 至少n次至多m次出现 |
{n,} | {n,}? | {n,}+ | 至少n次出现 |
浏览器对支配量词的支持还很不完善。IE和Opera不支持,Mozilla将支配量词看作是贪婪的。
二、复杂模式
1.分组
分组是通过一系列括号包围一系列字符、字符类以及量词来使用的。
/dogdog/可使用分组来重写成/(dog){2}/
/([bd]ad?)*/匹配零个和多个"ba","da","bad"或"dad"
/(mom( and dad)?)/匹配"mom" 或 "mom and dad"
2.反向引用
在表达式计算完成后还可以怎样利用分组?每个分组都被存放在一个特殊的地方以备将来使用。这些存储在分组中的特殊值,我们称之为反向引用。
反向引用是按照从左到右遇到的左括号字符的顺序进行创建和编号的。例如表达式(A?(B?(C?)))将产生编号从1-3的三个反向引用
(1).(A?(B?(C?)))
(2).(B?(C?))
(3).(C?)
反向引用可以有几种不同的使用方法。
首先,使用正则表达式对象的test(),match()或search()方法后,反向引用的值可以从RegExp构造函数中获得。例
var sToMatch = "#123456789";
var reNumbers = /#(\d+)/;
reNumbers.test(sToMatch);
alert(RegExp.$1); //outputs "123456789"
然后,还可以直接在定义分组的表达式中包含反向引用,这可以通过使用特殊转义序列如\1,\2等等实现
例如
var sToMatch = "dogdog";
var reDogDog = /(dog)\1/;
alert(reDogDog.test(sToMatch)); //outputs "true"
正则表达式reDogDog首先创建单词dog的组,然后又被特殊转义序列\1引用,使得这个正则表达式等同于/dogdog/
第三,反向引用可以用在String对象的replace()方法中,这通过使用特殊字符序列$1,$2等等来实现。例如
var sToChange = "1234 5678";
var reMatch = /(\d{4}) (\d{4})/
var sNew = sToChange.replace(reMatch,"$2 $1");
alert(sNew); //outputs "5678 1234"
3.候选
有时候要构建一个能够正确匹配想得到所有可能性的模式是十分困难的。如果要对同一个表达式同时匹配"red"和"break"时要怎么做呢?这些单词完全没有相同的字符,这样就要写两个不同的正则表达式,并分别对两个字符串进行匹配,像这样:
var sToMatch1 = "red";
var sToMatch2 = "black";
var reRed = /red/;
var reBlack = /black/;
alert(reRed.test(sToMatch1)||reBlack.test(sToMatch1)); //outputs "true"
alert(reRed.test(sToMatch2)||reBlack.test(sToMatch2)); //outputs "true"
这完成了任务,但是十分冗长。还有另一种方式就是使用正则表达式的候选操作符。例:
var sToMatch1 = "red";
var sToMatch2 = "black";
var reRedOrBlack = /(red|black)/;
alert(reRedOrBlack.test(sToMatch1)); //outputs "true"
alert(reRedOrBlack.test(sToMatch2)); //outputs "true"
4.非捕获性分组
创建反向引用的分组,我们称之为捕获性分组。同时还有一种非捕获性分组,它不会创建反向引用。在较长的正则表达式中,存储反向引用会降低匹配速度。
如果要创建一个非捕获性分组,只要在左括号的后面加上一个问号和一个紧跟的冒号:
var sToMatch = "#123456789";
var reNumbers = /#(?:\d+)/;
reNumbers.test(sToMatch);
alert(RegExp.$1); //outputs ""
5.前瞻
有时候,可能希望,当某个特定的字符分组出现在另一个字符串之前时,才去捕获它。如果使用“前瞻”就可以让这个过程变得十分简单。
前瞻,告诉正则表达式运算器向前看一些字符而不移动其位置。同样存在正向前瞻和负向前瞻。正向前瞻检查的是接下来出现的是不是某个特定字符集。而负向前瞻则是检查接下来的不应该出现的特定字符集。
创建正向前瞻要将模式放在(?=和)之间。注意这不是分组,虽然它也用到括号。
var sToMatch1 = "bedroom";
var sToMatch2 = "bedding";
var reBed = /(bed(?=room)/;
alert(reBed.test(sToMatch1)); //outputs "true"
alert(RegExp.$1); //outputs "bed"
alert(reBed.test(sToMatch2)); //outputs "false"
负向前瞻,则要将模式放在(?!和)之间。
var sToMatch1 = "bedroom";
var sToMatch2 = "bedding";
var reBed = /(bed(?!room)/;
alert(reBed.test(sToMatch1)); //outputs "false"
alert(reBed.test(sToMatch2)); //outputs "true"
alert(RegExp.$1); //outputs "bed"
6.边界
边界 用于正则表达式中表示模式的位置。下表列出了几种可能的边界
边界 | 描述 |
^ | 行开头 |
$ | 行结尾 |
\b | 单词的边界 |
\B | 非单词的边界 |
假设想查找一个单词,但要它只出现在行尾,则可以使用美元符号$来表示它:
var sToMatch = "Important word is the last one.";
var reLastWord = /(\w+).$/;
reLastWord.test(sToMatch);
alert(RegExp.$1); //outputs "one"
7.多行模式
要指定多行模式,只要在正则表达式后面添加一个m选项。这会让$边界匹配换行符(\n)以及字符串真正的结尾。
var sToMatch = "First second\nthird fourth\nfifth sixth";
var reLastWordOnLine = /(\w+)$/gm;
var arrWords = sToMatch.match(reLastWordOnLine);
表达式返回"second","fourth"和"sixth"。若不指定多行模式,表达式将只返回"sixth"。
二、RegExp对象
javascript中的每个正则表达式都是一个对象,同其他的对象一样。
1.实例属性
global--Boolean值,表示g(全局选项)是否已设置。
ignoreCase--Boolean值,表示i(忽略大小写选项)是否已设置。
lastIndex--整数,代表下次匹配将会从哪个字符位置开始(只有当使用exec()或test()函数才会填入,否则为0)。
multiline--Boolean值,表示m(多行模式选项)是否已设置。
source--正则表达式的源字符串形式。例如表达式/[ba]*/的source将返回"[ba]*"。
2.静态属性
静态的RegExp属性对所有的正则表达式都有效。
长名 | 短名 | 描述 |
input | $_ | 最后用于匹配的字符串(传递给exec()或test()的字符串) |
lastMatch | $& | 最后匹配的字符 |
lastParen | $+ | 最后匹配的分组 |
leftContext | $` | 在上次匹配的前面的子串 |
multiline | $* | 用于指定是否所有的表达式都使用多行模式的布尔值 |
rightContext | $' | 在上次匹配之后的子串 |
IE和Opera并不支持RegExp.multiline,所以最好单独的对每个表达式设置m选项而不要直接设置这个标记。