一、基本使用
在 JavaScript 中,可以用下面的两种方法来创建一个正则表达式(RegExp)对象:
var re = /fox/; var re = new RegExp("fox");
创建了 RegExp 对象后,就可以用 test() 方法来检测某个字符串是否匹配。例如:
var re = /fox/; var str = "The quick brown fox jumps over the lazy dog"; alert(re.test(str)); // true
test() 方法根据字符串是否匹配该正则表达式,返回 true 或者 false。
RegExp 对象还有另一个参数,用于指明匹配标志。该参数是字母 g, i 和 m 的任意组合。其中 g 表示全局模式,即查找全部匹配的子串;i 表示不区分大小写;m 表示多行模式,即让 ^ 和 $ 符也分别匹配行首和行尾(见下面的介绍)。例如
var re = /fox/gi; var re = new RegExp("fox", "gi");
二、选择符 |
如果我们要匹配 cat 或者 dog,可以用选择符 |。例如:
var re = /cat|dog/; var str = "The quick brown fox jumps over the lazy dog"; alert(re.test(str)); // true
三、字符集 []
如果我们需要匹配某些字符,可以用字符集符号 []。比如 [aeiou] 匹配 5 种元音字母。再如下面的例子:
var re = /f[aeiou]x/; var str = "The quick brown fox jumps over the lazy dog"; alert(re.test(str)); // true
由于字符串中包含 fox,所以匹配成功。如果我们需要匹配小写字母,不用一一列出,用 [a-z] 这种简写方式就可以了。类似地,[0-9] 匹配10个数字符号。相反地,如果要匹配非元音字母,可以用 [^aeiou]。方括号内部最前面的 ^ 符号表示补集。
同时,对常用的字符集,我们也有下面这些简记方式:
\0 | 匹配 NUL 字符 |
\b | 匹配位于单词的开头或结尾的位置 |
\B | 匹配不处在单词的开头或结尾的位置 |
\d | 匹配数字字符,等同于 [0-9] |
\D | 匹配非数字字符,等同于 [^0-9] |
\f | 匹配换页符 |
\n | 匹配换行符 |
\r | 匹配回车符 |
\s | 匹配 Unicode 空白字符,即 [\f\n\r\t\v \u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u205f\u3000\ufeff] |
\S | 匹配非 Unicode 空白字符,即 [^\f\n\r\t\v \u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u205f\u3000\ufeff] |
\t | 匹配制表符 |
\v | 匹配垂直制表符 |
\w | 匹配单词字符,等同于 [a-zA-Z0-9_] |
\W | 匹配非单词字符,等同于 [^a-zA-Z0-9_] |
. | 匹配单个字符,除了换行符和 Unicode 行终止符,即 [^\n\r\u2028\u2029] |
其中 \s \S . 这几个字符集,可能不同的浏览器的实现不一样。
四、重复符 ? * +
如果需要匹配某些重复的字符,可以在该字符后面加上重复符 ? 或 * 或 +。其中 ? 表示重复 0 次或 1 次,* 表示重复 0 次或多次,+ 表示重复 1 次或多次。例如:
var re1 = /9?/; var re2 = /9*/; var re3 = /9+/; var str = "The quick brown fox jumps over the lazy dog"; alert(re1.test(str)); // true alert(re2.test(str)); // true alert(re3.test(str)); // false
类似地,{2,} 表示匹配 2 次或以上,而 {2,5} 表示匹配至少 2 次而且至多 5 次。
五、非贪婪匹配
前面的 * 和 ? 的贪婪匹配的重复符,而 *? 和 +? 是对应的非贪婪匹配的重复符。贪婪匹配将得到最长的匹配,而非贪婪匹配将得到最短的匹配。例如:
/-.+-/.exec("-ab-cd-e") // -ab-cd- /-.+?-/.exec("-ab-cd-e") // -ab-
六、字符串开头和结束
使用 ^ 和 $,可以分别匹配字符串开头和结束的位置。例如:/^[1-9]\d*$/ 匹配一个正整数。如果该正则表达式有 m 标志,则它们也可以分别匹配行首和行尾。此时,字符串的各行由 \r 和 \n 分割。
七、捕获组和非捕获组
用 (x) 包含的内容为一个捕获组,而用 (?:x) 包含的内容为一个非捕获组。捕获组的内容将出现在 re.exec(str) 和 str.search(re) 函数的返回值里面。另外,我们可以用 \1,\2 分别引用前面的第 1 个,第 2 个捕获组的内容,等。这些捕获组按照左括号出现的顺序编号。
八、向前查找
x(?=y) 表示当 x 在 y 之前时匹配 x,而 x(?!y) 当 x 不在 y 之前时匹配 x。对这两种情形,y 都不包含在匹配的字符串中。例如:
/-\w+(?!-)/.exec("a-bcd-") // 'bc'
九、特殊字符
在正则表达式中,( ) [ ] { } \ ^ $ . | ? * + 这 14 个字符是特殊字符,要匹配这些字符,必须在它们前面用反斜杠 \ 进行转义。
十、相关函数列表
与正则表达式相关的函数主要在 RegExp 对象和 String 对象中,包括下面这些函数。
re.test(str) 和 str.search(re):判断字符串和正则表达式是否匹配,前者返回值为 true 或者 false,后者返回值为匹配子串的起始位置。
re.exec(str) 和 str.match(re): 查找字符串中和正则表达式匹配的子字符串。
如果正则表达式中没有 g 标志,两者的返回值是一样的:匹配成功返回值为数组,这个数组的第一项为所匹配的子字符串,后面各项为各个捕获组的内容;返回的数组中还包含两个属性 index 和 input,分别表示所匹配的位置和输入字符串;匹配失败返回值为 null。
如果正则表达式中有 g 标志,两者的返回值不一样:前者的返回值和不含 g 标志时类似,但此时正则表达式 re 中多了一个 lastIndex 属性,指明下次搜索的开始位置,如果匹配不成功则 lastIndex 属性被重置为 0。而后者的返回值包含所有匹配的子字符串,而且不再有 index 和 input 属性。
如果我们需要得到所有匹配的字符串的位置,只能用 re.exec(str)。例如:
var re = /(\n|\r\n){2,}/g; var str = "ab\n\ncd\n\n\nef"; var result, i = 0, msg; while ((result = re.exec(str)) !== null) { msg = "Found a paragraph at " + i + '-' + result.index + ". "; msg += "Next match starts at " + re.lastIndex; console.log(msg); i = re.lastIndex; } if (i < str.length) { console.log("Found a paragraph at " + i + '-' + str.length + "."); } // Found a paragraph at 0-2. Next match starts at 4 // Found a paragraph at 4-6. Next match starts at 9 // Found a paragraph at 9-11.
str.replace(re, newstr):将 str 中与正则表达式匹配的子字符串替换为 newstr。默认只替换一次,如果要替换多次需要在正则表达式中加上 g 标志。例如:
var str = 'one apple and two apples'; var re1 = /apple/, re2 = /apple/g; var newstr = 'banana'; console.log(str.replace(re1, newstr)); // one banana and two apples console.log(str.replace(re2, newstr)); // one banana and two bananas
另外,在 replace 的第二个参数 newstr 中,$ 字符有如下特殊含义(因此 newstr 包含 $ 时需要小心):
- $& :表示所匹配的子字符串
- $`:表示所匹配的子字符串之前的字符串
- $' :表示所匹配的子字符串之后的字符串
- $n 或 $nn:表示第 n 或 nn 个捕获组的内容
- $$ :表示字符 $
这个 replace 方法的第二个参数也可以是一个函数,即 str.replace(re, func)。此时替换函数 func 的参数中,第一个为所匹配的子字符串,接下来为各个捕获组的内容;接下来是匹配子串的起始位置,最后一个参数是所查找的字符串。该替换函数的返回值将作为替换的内容。例如:
text.replace(/[<>\&\"\']/g, function(c) { return '&#' + c.charCodeAt(0) + ';'; });
这个例子中,我们将 HTML 的预留字符替换成它的字符实体。
参考资料:
[1] RegExp - JavaScript | MDN
[2] test - JavaScript | MDN
[3] exec - JavaScript | MDN
[4] String.match - JavaScript | MDN
[5] search - JavaScript | MDN
[6] replace - JavaScript | MDN
[7] JavaScript RegExp 对象参考手册
[8] Online RegExp Tester (1) (2)
[9] javascript之正则表达式 (一) (二)
[A] 深入浅出之正则表达式 (一) (二)
[B] JavaScript, Regex, and Unicode
[C] JavaScript Regex and Unicode Tests
[YAML] Updated: 2014-01-12 10:23:00