下面我们来补习一些正则语法。
JS有2种预编译正则的方法:
var pat = /test/;
var pat = new RegExp("test");
这2者的区别是,第一种是写死在代码中的,第二种可以通过动态构造字符串获得。
但是,在字符串中""是转义符,所以一些常用集合需要加2个"",如\s
要写成"\\s"
。这使得本来就语法怪异的正则写起来更加容易出错。
所以,我们更倾向于第一种写法。
另外,还有3个标志位,可以控制正则的作用方式:
- i -- 大小写不敏感
- g -- global匹配,否则只匹配第一个
- m -- 允许跨行匹配,比如对于textarea中的文本
示例如下:
var pat = /test/gi;
var pat = new RegExp("test", "gi");
这种最简单,只要不是特殊字符,就要和他本身匹配才行,如/test/
就只能匹配"test"
从一个集合中匹配,有3种形式
- 指定全部包含集合,和集合中的一个匹配就行:
[abc]
可以分别匹配a或b或c - 指定全部不包含集合,不要和其中任何一个匹配:
[^abc]
可以匹配任何不是a或b或c的字符 - 指定一个连续集合:
[a-z]
匹配a到z的所有字符
如果要匹配特殊字符,如上面提到的[, ], -,同时还有^ $ .等等,都需要用反斜杠转义
如果匹配\
,需要用2个\\
如果是字符串,需要多写一个\,如"\\"其实匹配"\"
^表示字符串的开头,$表示字符串的结尾。可以把它们当成2个特殊字符。正则中的字符串都是“跟随”关系,如 /test/表示t要跟着e,e要跟着s,s要跟着t。所以/^test/表示开头后面要跟着t,即以test开头, /test$/表示以test结尾,/^test$/表示一行中只有test。
正则表达式有以下几种指定重复次数的方法:
- 通过?指定可选字符,如/t?est/就指定t可有可无
- 通过+指定字符重复次数为大于等于1次。如/t+est/可以匹配"test", "ttest", "ttttttest", 但是不能匹配"est"
- 星号*的作用与+类似,只是/t*est/可以匹配"est"
- 指定固定重复次数,如/a{4}/只能匹配"aaaa"
- 指定固定重复范围,如/a{4,10}/可以匹配4到10次连续出现的a。第二个参数可省,说明最多可重复无穷多次
以上所有匹配都分"greedy"和"nongreedy"两种。默认情况下是greedy,即匹配最长满足条件的部分;如果在操作符后面增加?,就变成nongreedy的, 即匹配最短满足条件的部分。这里相当于对?进行了重载。
比如,对于字符串"aaa", /a+/会匹配全部3个a,/a+?/则只匹配一个a
正则里面有很多预定义的字符类,原因有2个,1是很多控制字符无法用[]表示,2是很多类特别常用,所以固定成一类。 他们的含义具体见下表:
Table7.1 Predefined character class and character terms
预定义类 | 匹配规则 |
---|---|
\t | 水平tab |
\b | 退格backspace |
\v | 垂直tab |
\f | 换到下一页开头 form feed |
\r | 回车 |
\n | 换行 |
\cA : \cZ | 控制字符 |
\x0000 : \xffff | unicode十六进制编码 |
\x00 : \xff | ASCII十六进制 |
. | 除了换行以外的所有字符 |
\d | 所有数字,等效于[0-9] |
\D | 所有非数字,等效于 [^0-9] |
\w | 所有字母数字,包括下划线,等效于 [A-Za-z0-9_] |
\W | 除了字母数字下划线以外的字符,等效于 [^A-Za-z0-9_] |
\s | 所有空白字符,包括空格,以及上面提到的tab,backspace,form feed等等 |
\S | 除了空白字符之外的字符, |
\b | 单词边界 |
\B | 非单词边界,即单词内部 |
加号+、星号*只会影响它前面的一个字符,如果我们希望影响多个字符,就需要把他们括起来,如/(ab)+/
匹配多次重复的ab组合。
同时圆括号还有第二个作用,它能捕获当前匹配的结果。关于“捕获”,我们将在7.4深入讲解
“或”操作用管道符号表示,如/a|b/既能匹配a,也能匹配b,/(ab)|(xy)/既能匹配ab,也能匹配xy
正则中最复杂的部分应该就是反向引用之前捕获的结果了。我们将在7.4深入讲解。在此你只需要知道,它代表了正则中已经匹配的一部分字符。 我们用\1、\2、\3分别表示从前到后的各次匹配结果。
例如,/[dtn]a\1/
表示匹配"a左右两边都是相同字符,并且相同的字符只能是d、t、n之一"这种模式。如dad,tat,nan,
但是不能匹配dat。这是它和/[dtn]a[dtn]/
的主要区别,理解这一点非常重要。
这种模式的好处在于,他可以方便匹配类似xml的标记文本,如
/<(\w+)>(.+)<\/\1>/
它允许我们正确匹配到形如<strong>hello</strong>
这样的字符串。否则这个功能将是不可能完成的,因为闭合部分取决于开始部分,是动态变化的,
它们必须正确配对才行。
好了,现在我们已经知道正则表达式是干嘛的了,下面我们来看看如何使用它们。