Skip to content

Latest commit

 

History

History
128 lines (87 loc) · 5.24 KB

File metadata and controls

128 lines (87 loc) · 5.24 KB

7.2 A regular expression refresher

下面我们来补习一些正则语法。

7.2.1 Regular expressions explained

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");

7.2.2 Terms and operators

EXACT MATCHING

这种最简单,只要不是特殊字符,就要和他本身匹配才行,如/test/就只能匹配"test"

MATCHING FROM A CLASS OF CHARACTERS

从一个集合中匹配,有3种形式

  1. 指定全部包含集合,和集合中的一个匹配就行:[abc]可以分别匹配a或b或c
  2. 指定全部不包含集合,不要和其中任何一个匹配:[^abc]可以匹配任何不是a或b或c的字符
  3. 指定一个连续集合:[a-z]匹配a到z的所有字符
ESCAPING

如果要匹配特殊字符,如上面提到的[, ], -,同时还有^ $ .等等,都需要用反斜杠转义 如果匹配\,需要用2个\\

如果是字符串,需要多写一个\,如"\\"其实匹配"\"

BEGINS AND ENDS

^表示字符串的开头,$表示字符串的结尾。可以把它们当成2个特殊字符。正则中的字符串都是“跟随”关系,如 /test/表示t要跟着e,e要跟着s,s要跟着t。所以/^test/表示开头后面要跟着t,即以test开头, /test$/表示以test结尾,/^test$/表示一行中只有test。

REPEATED OCCURRENCES

正则表达式有以下几种指定重复次数的方法:

  • 通过?指定可选字符,如/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

PREDEFINED CHARACTER CLASSES

正则里面有很多预定义的字符类,原因有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 非单词边界,即单词内部
GROUPING

加号+、星号*只会影响它前面的一个字符,如果我们希望影响多个字符,就需要把他们括起来,如/(ab)+/匹配多次重复的ab组合。 同时圆括号还有第二个作用,它能捕获当前匹配的结果。关于“捕获”,我们将在7.4深入讲解

ALTERNATION (OR)

“或”操作用管道符号表示,如/a|b/既能匹配a,也能匹配b,/(ab)|(xy)/既能匹配ab,也能匹配xy

BACKREFERENCES

正则中最复杂的部分应该就是反向引用之前捕获的结果了。我们将在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>这样的字符串。否则这个功能将是不可能完成的,因为闭合部分取决于开始部分,是动态变化的, 它们必须正确配对才行。

好了,现在我们已经知道正则表达式是干嘛的了,下面我们来看看如何使用它们。