JavaScript中的RegExp正则表达式你知道多少?(建议收藏)

46 阅读2分钟

RegExp 类型支持正则表达式。正则表达式使用类似 Perl 的简洁语法来创建:

let expression = /pattern/flags;

这个正则表达式的 pattern(模式)可以是任何简单或复杂的正则表达式,包括字符类、限定符、

分组、向前查找和反向引用。每个正则表达式可以带零个或多个 flags(标记),用于控制正则表达式的行为。下面给出了表示匹配模式的标记。

 g:全局模式,表示查找字符串的全部内容,而不是找到第一个匹配的内容就结束。

 i:不区分大小写,表示在查找匹配时忽略 pattern 和字符串的大小写。

 m:多行模式,表示查找到一行文本末尾时会继续查找。

 y:粘附模式,表示只查找从 lastIndex 开始及之后的字符串。

 u:Unicode 模式,启用 Unicode 匹配。

 s:dotAll 模式,表示元字符.匹配任何字符(包括\n 或\r)。

使用不同模式和标记可以创建出各种正则表达式,比如:

// 匹配字符串中的所有"at"

let pattern1 = /at/g;

// 匹配第一个"bat"或"cat",忽略大小写

let pattern2 = /[bc]at/i;

// 匹配所有以"at"结尾的三字符组合,忽略大小写

let pattern3 = /.at/gi;

与其他语言中的正则表达式类似,所有元字符在模式中也必须转义,包括:108 第 5 章 基本引用类型

( [ { \ ^ $ | ) ] } ? * + .

元字符在正则表达式中都有一种或多种特殊功能,所以要匹配上面这些字符本身,就必须使用反斜

杠来转义。下面是几个例子:

// 匹配第一个"bat"或"cat",忽略大小写

let pattern1 = /[bc]at/i;

// 匹配第一个"[bc]at",忽略大小写

let pattern2 = /\[bc\]at/i;

// 匹配所有以"at"结尾的三字符组合,忽略大小写

let pattern3 = /.at/gi;

// 匹配所有".at",忽略大小写

let pattern4 = /\.at/gi;

这里的 pattern1 匹配"bat"或"cat",不区分大小写。要直接匹配"[bc]at",左右中括号都必

须像 pattern2 中那样使用反斜杠转义。在 pattern3 中,点号表示"at"前面的任意字符都可以匹配。

如果想匹配".at",那么要像 pattern4 中那样对点号进行转义。

前面例子中的正则表达式都是使用字面量形式定义的。正则表达式也可以使用 RegExp 构造函数来

创建,它接收两个参数:模式字符串和(可选的)标记字符串。任何使用字面量定义的正则表达式也可

以通过构造函数来创建,比如:

// 匹配第一个"bat"或"cat",忽略大小写

let pattern1 = /[bc]at/i;

// 跟 pattern1 一样,只不过是用构造函数创建的

let pattern2 = new RegExp("[bc]at", "i");

这里的 pattern1 和 pattern2 是等效的正则表达式。注意,RegExp 构造函数的两个参数都是字

符串。因为 RegExp 的模式参数是字符串,所以在某些情况下需要二次转义。所有元字符都必须二次转 义,包括转义字符序列,如\n(\转义后的字符串是\\,在正则表达式字符串中则要写成\\\\)。下表 展示了几个正则表达式的字面量形式,以及使用 RegExp 构造函数创建时对应的模式字符串。

/\[bc\]at/ "\\[bc\\]at"

/\.at/ "\\.at"

/name\/age/ "name\\/age"

/\d.\d{1,2}/ "\\d.\\d{1,2}"

/\w\\hello\\123/ "\\w\\\\hello\\\\123"

此外,使用 RegExp 也可以基于已有的正则表达式实例,并可选择性地修改它们的标记:

const re1 = /cat/g;

console.log(re1); // "/cat/g"

const re2 = new RegExp(re1);

console.log(re2); // "/cat/g"

const re3 = new RegExp(re1, "i");

console.log(re3); // "/cat/i"

RegExp 实例属性

每个 RegExp 实例都有下列属性,提供有关模式的各方面信息。

- global:布尔值,表示是否设置了 g 标记。

- ignoreCase:布尔值,表示是否设置了 i 标记。

- unicode:布尔值,表示是否设置了 u 标记。

- sticky:布尔值,表示是否设置了 y 标记。

- lastIndex:整数,表示在源字符串中下一次搜索的开始位置,始终从 0 开始。

- multiline:布尔值,表示是否设置了 m 标记。

- dotAll:布尔值,表示是否设置了 s 标记。

- source:正则表达式的字面量字符串(不是传给构造函数的模式字符串),没有开头和结尾的

斜杠。

- flags:正则表达式的标记字符串。始终以字面量而非传入构造函数的字符串模式形式返回(没 有前后斜杠)。

通过这些属性可以全面了解正则表达式的信息,不过实际开发中用得并不多,因为模式声明中包含

这些信息。下面是一个例子:

let pattern1 = /\[bc\]at/i;

console.log(pattern1.global); // false

console.log(pattern1.ignoreCase); // true

console.log(pattern1.multiline); // false

console.log(pattern1.lastIndex); // 0

console.log(pattern1.source); // "\[bc\]at"

console.log(pattern1.flags); // "i"

let pattern2 = new RegExp("\\[bc\\]at", "i");

console.log(pattern2.global); // false

console.log(pattern2.ignoreCase); // true

console.log(pattern2.multiline); // false

console.log(pattern2.lastIndex); // 0

console.log(pattern2.source); // "\[bc\]at"

console.log(pattern2.flags); // "i"

注意,虽然第一个模式是通过字面量创建的,第二个模式是通过 RegExp 构造函数创建的,但两个

模式的 source 和 flags 属性是相同的。source 和 flags 属性返回的是规范化之后可以在字面量中

使用的形式。

RegExp 构造函数属性

RegExp 构造函数本身也有几个属性。(在其他语言中,这种属性被称为静态属性。)这些属性适用

于作用域中的所有正则表达式,而且会根据最后执行的正则表达式操作而变化。这些属性还有一个特点,112 第 5 章 基本引用类型

就是可以通过两种不同的方式访问它们。换句话说,每个属性都有一个全名和一个简写。下表列出了

RegExp 构造函数的属性

input $_ 最后搜索的字符串(非标准特性)

lastMatch $& 最后匹配的文本

lastParen $+ 最后匹配的捕获组(非标准特性)

leftContext $` input 字符串中出现在 lastMatch 前面的文本

rightContext $' nput 字符串中出现在 lastMatch 后面的文本

通过这些属性可以提取出与 exec()和 test()执行的操作相关的信息。来看下面的例子:

let text = "this has been a short summer";

let pattern = /(.)hort/g;

if (pattern.test(text)) {

console.log(RegExp.input); // this has been a short summer

console.log(RegExp.leftContext); // this has been a

console.log(RegExp.rightContext); // summer

console.log(RegExp.lastMatch); // short

console.log(RegExp.lastParen); // s

}

以上代码创建了一个模式,用于搜索任何后跟"hort"的字符,并把第一个字符放在了捕获组中。

不同属性包含的内容如下。

 input 属性中包含原始的字符串。

 leftConext 属性包含原始字符串中"short"之前的内容,rightContext 属性包含"short"

之后的内容。

 lastMatch 属性包含匹配整个正则表达式的上一个字符串,即"short"。

 lastParen 属性包含捕获组的上一次匹配,即"s"。

这些属性名也可以替换成简写形式,只不过要使用中括号语法来访问,如下面的例子所示,因为大

多数简写形式都不是合法的 ECMAScript 标识符:

let text = "this has been a short summer";

let pattern = /(.)hort/g;

/*

* 注意:Opera 不支持简写属性名

* IE 不支持多行匹配

*/

if (pattern.test(text)) {

console.log(RegExp.$_); // this has been a short summer

console.log(RegExp["$`"]); // this has been a

console.log(RegExp["$'"]); // summer

console.log(RegExp["$&"]); // short

console.log(RegExp["$+"]); // s

}

RegExp 还有其他几个构造函数属性,可以存储最多 9 个捕获组的匹配项。这些属性通过 RegExp.

1 RegExp.1~RegExp.9 来访问,分别包含第 1~9 个捕获组的匹配项。在调用 exec()或 test()时,这些属属就会被填充,然后就可以像下面这样使用它们:

let text = "this has been a short summer";

let pattern = /(..)or(.)/g;

if (pattern.test(text)) {

console.log(RegExp.$1); // sh

console.log(RegExp.$2); // t

}

在这个例子中,模式包含两个捕获组。调用 test()搜索字符串之后,因为找到了匹配项所以返回

true,而且可以打印出通过 RegExp 构造函数的11 和2 属性取得的两个捕获组匹配的内容。