正则表达式(Regular Expressions)是用于匹配字符串中字符组合的模式。在 JavaScript 中,正则表达式也是对象。这些模式被用于 RegExp
的 exec
和 test
方法, 以及 String
的 match
、matchAll
、replace
、search
和 split
方法。
创建正则表达式的方式有两种:
// 正则表达式字面量
var re = /ab+c/;
// 使用 RegExp 对象的构造函数
var re = new RegExp("ab+c");
1. 正则表达式中的特殊字符
-
\
为转义,通常在\
后面的字符不按原本的意义解释。如/b/
匹配字符"b"
,当 b 前面添加反斜杠/\b/
,转义为匹配一个单词的边界。也可以对正则表达式功能字符的还原,/a*/
将匹配"a"
、"aa"
、"aaa"
等字符(*
匹配它前面元字符 0 次或多次,),加了反斜杠后/a\*/
将只匹配"a*"
。 -
^
匹配一个输入或一行的开头,/^a/
匹配"an A"
字符,而不匹配"An a"
字符。 -
$
匹配一个输入或一行的结尾,/a$/
匹配"An a"
字符,而不匹配"an A"
字符。 -
*
匹配前面元字符 0 次或多次,/ba*/
匹配"b"
、"ba"
、"baa"
、"baaa"
等字符。 -
+
匹配前面元字符 1 次或多次,/ba+/
匹配"ba"
、"baa"
、"baaa"
等字符。 -
?
匹配前面元元字符 0 次或 1 次,/ba?/
匹配"b"
、"ba"
字符。 -
(x)
匹配x
,保存x
在$1...$9
的变量中。 -
x|y
匹配x
或y
。 -
{n}
精确匹配 n 次。 -
{n,}
精确匹配 n 次及以上。 -
{m,n}
精确匹配m ~ n
次。 -
[xyz]
字符集,匹配这个集合中的任一一个字符(或元字符)。 -
[^xyz]
不匹配这个集合中的任一一个字符。 -
[\b]
匹配一个退格符。 -
\b
匹配一个单词的边界。 -
\B
匹配一个单词的非边界。 -
\cX
这里的X
是一个控制符,\cM/
匹配Ctrl-M
。 -
\d
匹配一个数字字符,/\d/
相当于/[0-9]/
。 -
\D
匹配一个非数字字符,/\D/
相当于/[^0-9]/
。 -
\n
匹配一个换行符。 -
\r
匹配一个回车符。 -
\s
匹配一个空白字符,包括\n
、\r
、\f
、\t
、\v
等,相当于/[\n\r\f\t\v]/
。 -
\S
匹配一个非空白字符,相当于/[^\n\r\f\t\v]/
。 -
\t
匹配一个制表符。 -
\v
匹配一个垂直制表符。 -
\w
匹配一个可以组成单词的字符(包括字母、数字或者下划线)。如[\w]
匹配"$5.28"
中的5
,相当于[a-zA-Z0-9]
。 -
\W
匹配一个不可以组成单词的字符,如[\W]
匹配"$5.28"
中的$
,相当于[^a-zA-Z0-9]
。
2. 直接量字符
如果想在正则表达式中使用特殊的标点符号,必须在他们之前加上一个 \
进行转义。
-
\/
表示一个/
直接量。 -
\\
表示一个\
直接量。 -
\.
表示一个.
直接量。 -
\*
表示一个*
直接量。 -
+
表示一个+
直接量。 -
?
表示一个?
直接量。 -
\|
表示一个|
直接量。 -
\(
表示一个(
直接量。 -
\)
表示一个)
直接量。 -
\[
表示一个[
直接量。 -
\]
表示一个]
直接量。 -
\{
表示一个{
直接量。 -
\}
表示一个}
直接量。
3. 字符类
将单独的直接复放进中括号([...]
)内就可以组合成字符类。一个字符类和它所包含的任何一个字符都匹配。正式表达式 /[abc]/
和字母 "a"
、"b"
、"c"
中的任何一个都匹配,另外还可以定义否定字符类,这些类匹配的是除那些包含在中括号之内的字符外的所有字符。定义否定字符尖(^
)时,要将一个 ^
符号作为从左中括号算起的第一个字符。
由于某些字符类非常常用,所以 JavaScript 的正则表达式语法包含一些特殊字符和转义序列来表示这些常用的类。比如 \s
匹配的是空白符(包括空格符、制表符、换行符等空白符),\S
匹配的是除空白符之外的任意字符。
-
[...]
匹配位于括号之内的任意字符。 -
[^...]
匹配不在括号内的任意字符。 -
.
匹配除换行符之外的任意字符,相当于[^\n]
。 -
\w
匹配任何单字字符,相当于[a-zA-Z0-9_]
。 -
\W
匹配任何非单字字符,相当于[^a-zA-Z0-9_]
。 -
\s
匹配任意空白符,相当于/[\n\r\f\t\v]/
。 -
\S
匹配任意非空白符,相当于/[^\n\r\f\t\v]/
。 -
\d
匹配任意数字,相当于[0-9]
。 -
\D
匹配除数字之外的任意字符,相当于[^0-9]
。 -
\b
匹配一个退格直接量(特例)。
4. 复制
用以上的正则表达式语法,可以把两位数描述成 /\d\d/
,把四位数描述成 /\d\d\d\d/
,但是我们还没有一种方法可以用来描述具有任意多位数的数字或者是一个字符串,这个字符串由三个字符以及跟随在字母后的一位数字构成。这些复杂的模式使用的正则表达式语法指定了改表达式中每个元素要重复出现的次数。
指定复制的字符总是出现在它们所作用的模式后面。由于某种复制类型相对常用。所以有一些特殊的字符专门用于表示它们。比如 +
匹配的就是复制前一模式一次或多次的模式下。
先看写例子:
-
/\d{2,4}/
表示匹配 2 ~ 4 个的数字字符。 -
/\w{3}\d?/
表示匹配三个单字字符和一个任意的数字。 -
\s+java\s+
表示匹配字符串"java"
,并且该字符串前后可以有一个或多个空格。 -
/[^"]*/
表示匹配零个或多个非引号字符。
复制字符的几种方式:
-
{m,n}
匹配前一项至少 m 次,但是不能超过 n 次。 -
{n,}
匹配前一项 n 次及以上。 -
{n}
匹配前一项恰好 n 次。 -
?
匹配前一项 0 次或 1 次,就是说前一项是可选的,相当于{0,1}
。 -
+
匹配前一项 1 次或多次,相当于{1,}
。 -
*
匹配前一项 0 次或多次,相当于{0,}
。
5. 选择、分组、引用
正则表达式的语法还包括指定选择项,对子表达式分组和引用前一子表达式的特殊字符。字符 |
用于分隔供选择的字符,例如:/ab|cd|ef/
匹配的是 "ab"
或者是 "cd"
又或者是 "ef"
字符串。再比如:/\d{3}|[a-z]{4}/
匹配的是要么是一个三位数字,要么是四个小写字母。
在正则表达式中,括号((...)
)具有几种作用:
1️⃣ 它的主要作用是把单独的项目分组成子表达式,以便可以像处理一个独立的单元那种用 *
、+
或 ?
来处理那些项目。例如:/java(script)?/
匹配的是字符串 "java"
,其后的既可以有 "script"
,也可以没有。再比如,/(ab|cd)+|ef/
匹配的既可以是字符串 "ef"
,也可以是字符串 "ab"
或者 "cd"
的一次或多次重复。
2️⃣ 括号的第二个用途是,在完整的模式中定义子模式。当一个正则表达式成功地和目标字符串相匹配是,可以从目标串中抽出和括号中的子模式相匹配的部分。例如,假定我们正在检索的模式是一个或多个字母后面跟随一位或多位数组,你们我们可以使用模式 /[a-z]+\d+/
。但是由于假定我们真正关心的是每个匹配尾部的数字,那么如果我们将模式的数字部分放在括号中 /[a-z]+(\d+)/
,我们就可以从所检索到的任何匹配中抽取数字了,之后我们会对此进行解析的。
3️⃣ 代括号的另一个用途是,允许我们在同一正则表达式的后面引用前面的子表达式。这是通过在字符串 \
后加一位或多位数字来实现的。数字指的是代括号的子表达式在正则表达式中的位置。例如:\1
引用的的是第一个代括号的子表达式,\3
引用的是第三个代括号的子表达式。注意,由于子表达式可以嵌套在其他子表达式中,所以它的位置是被计数的左括号的位置。
例如,在下面的正则表达式被指定为 \2
:/([Jj]ava[Ss]cript)\sis\s(fun\w*)/
,对正则表达式中前一子表达式的引用所指定的并不是那个子表达式,而是与那个模式相匹配的文本。这样,引用就不只是帮助你输入正则表达式的重复部分的快捷方式了,它还实施了一条规约,那就是一个字符串各个分离的部分包含的是完全相同的字符。例如:/['"][^'"]['"]/
匹配的就是位于单引号或者双引号之内的所有字符。但是它要求开始和结束的引号匹配。(例如两个都是双引号或者都是但引号)
如果要求开始和结束的引号匹配,我们可以使用如下的引用:/(['"])[^'"]*\1/
,\1
匹配的是第一个代括号的子表达式所匹配的模式。在这个例子中,它实施了一种规约,那就是开始的引号必须和结束的引号相匹配。注意,如果反斜杠后跟随的数字比代括号的子表达式数多,那么它就会被解析为一个十进制的转义序列,而不是一个引用。你可以坚持使用完整的三个字符来表示转义序列,这样就可以避免混淆了。例如 \044
,而不是 \44
。
下面是正则表达式的选择、分组和引用字符:
-
|
选择:匹配的要么是该符号左边的子表达式,要么是它右边的子表达式。 -
(...)
分组:将几个项目分为一个单元,这个单元可由*
、+
、?
和|
等符号使用,而且还可以记住和这个组匹配的字符以供此后引用使用\n
和第n
个(注意这里的n
是指数字)分组所匹配的字符相匹配。分组是括号中的子表达式。(可能是嵌套的)分组号是从左到右计数的左括号数。
6. 通过标志进行高级搜索
正则表达式有六个可选参数(flags
)允许全局和不分大小写搜索等。这些参数既可以单独使用,也能以任意顺序一起使用,并且被包含在正则表达式实例中。
-
g
全局搜索 -
i
不区分大小写搜索 -
m
多行搜索。 -
s
允许.
匹配换行符。 -
u
使用 unicode 码的模式进行匹配。 -
y
执行“粘性(sticky)”搜索,匹配从目标字符串的当前位置开始。
// 正则表达式字面量
var re = /pattern/flags;
// RegExp 构造函数
var re = new RegExp("pattern", "flags");
7. 动态创建正则表达式
从用户输入等来源中动态地产生,就需要使用构造函数来创建正则表达式。
// 假设需求是生成一个正则表达式:/temp/
// 此时我们手上有一个字符串 "temp"
var str = 'temp';
// 这种方式是不对的,得到的只是一个 "/temp/" 字符串。
var re = '/' + str + '/';
// 应该是这样,才是正则表达式
var re = new RegExp(str);
未完待续...