什么是正则
创建
字面量创建
ECMAScript 通过 RegExp 类型支持正则表达式。正则表达式使用类似 Perl 的简洁语法来创建:
let expression = /pattern/flags;
构造函数创建
// 匹配第一个"bat"或"cat",忽略大小写
let pattern1 = /[bc]at/i;
// 跟 pattern1 一样,只不过是用构造函数创建的
let pattern2 = new RegExp("[bc]at", "i");
因为 RegExp 的模式参数是字符串,所以在某些情况下需要二次转义。所有元字符都必须二次转义,包括转义字符序列,如\n(\转义后的字符串是\,在正则表达式字符串中则要写成\\)。
在此不做过多说明 ,更加推荐使用字面量创建。
pattern(模式)
这个正则表达式的 pattern(模式)可以是任何简单或复杂的正则表达式,包括
- 字符类
- 限定符
- 分组
- 向前查找
- 反向引用。
flags(标记)
每个正则表达式可以带零个或多个 flags(标记),用于控制正则表达式的行为。下面给出了表示匹配模式的标记。
| 名称 | flags | 意义 |
|---|---|---|
| 全局模式 | g | 查找字符串的全部内容,而不是找到第一个匹配的内容就结束 |
| 不区分大小写 | i | 查找匹配时忽略 pattern 和字符串的大小写 |
| 多行模式 | m | 表示查找到一行文本末尾时会继续查找 |
| 粘附模式 | y | 只查找从 lastIndex 开始及之后的字符串 |
| Unicode 模式 | u | 启用 Unicode 匹配 |
| dotAll 模式 | s | 表示元字符.匹配任何字符(包括\n 或\r) |
使用不同模式和标记可以创建出各种正则表达式,比如:
// 匹配字符串中的所有"at"
let pattern1 = /at/g;
// 匹配第一个"bat"或"cat",忽略大小写
let pattern2 = /[bc]at/i;
// 匹配所有以"at"结尾的三字符组合,忽略大小写
let pattern3 = /.at/gi;
元字符
与其他语言中的正则表达式类似,所有元字符在模式中也必须转义,包括:
( [ { \ ^ $ | ) ] } ? * + .
元字符在正则表达式中都有一种或多种特殊功能,所以要匹配上面这些字符本身,就必须使用反斜杠来转义。
// 匹配第一个"bat"或"cat",忽略大小写
let pattern1 = /[bc]at/i;
// 匹配第一个"[bc]at",忽略大小写
let pattern2 = /[bc]at/i;
// 匹配所有以"at"结尾的三字符组合,忽略大小写
let pattern3 = /.at/gi;
// 匹配所有".at",忽略大小写
let pattern4 = /.at/gi;
RegExp的实例属性
| 属性 | 类型 | 意义 |
|---|---|---|
| global | 布尔值 | 表示是否设置了 g 标记 |
| ignoreCase | 布尔值 | 表示是否设置了 i 标记 |
| unicode | 布尔值 | 表示是否设置了 u 标记 |
| sticky | 布尔值 | 表示是否设置了 y 标记 |
| multiline | 布尔值 | 表示是否设置了 m 标记 |
| dotAll | 布尔值 | 表示是否设置了 s 标记 |
| lastIndex | 整数 | 表示在源字符串中下一次搜索的开始位置,始终从 0 开始 |
| source | 正则表达式的字面量字符串(不是传给构造函数的模式字符串) | 没有开头和结尾的斜杠 |
| flags | 正则表达式的标记字符串 | 始终以字面量而非传入构造函数的字符串模式形式返回(没有前后斜杠) |
RegExp实例方法
exec()
用于配合捕获组使用。这个方法只接收一个参数,即要应用模式的字符串。
- 如果找到了匹配项,则返回包含第一个匹配信息的数组
- 如果没找到匹配项,则返回null。
返回的数组虽然是 Array 的实例,但包含两个额外的属性:
- index (字符串中匹配模式的起始位置)
- input(要查找的字符串)
这个数组的第一个元素是匹配整个模式的字符串,其他元素是与表达式中的捕获组匹配的字符串。如果模式中没有捕获组,则数组只包含一个元素。
let text = "mom and dad and baby";
let pattern = /mom( and dad( and baby)?)?/gi;
let matches = pattern.exec(text);
[
'mom and dad and baby',
' and dad and baby',
' and baby',
index: 0,
input: 'mom and dad and baby',
groups: undefined
]
如果模式设置了全局标记,则每次调用 exec()方法会返回一个匹配的信息。如果没有设置全局标
记,则无论对同一个字符串调用多少次 exec(),也只会返回第一个匹配的信息
let text = "cat, bat, sat, fat";
let pattern = /.at/g;
let matches1 = pattern.exec(text);
// [ 'cat', index: 0, input: 'cat, bat, sat, fat', groups: undefined ]
let matches2 = pattern.exec(text);
// [ 'bat', index: 5, input: 'cat, bat, sat, fat', groups: undefined ]
let matches3 = pattern.exec(text);
// [ 'sat', index: 10, input: 'cat, bat, sat, fat', groups: undefined ]
test()
接收一个字符串参数。如果输入的文本与模式匹配,则参数返回 true,否则返回 false。这个方法适用于只想测试模式是否匹配,而不需要实际匹配内容的情况。test()经常用在 if 语句中。
let text = "000-00-0000";
let pattern = /\d{3}-\d{2}-\d{4}/;
if (pattern.test(text)) {
console.log("The pattern was matched.");
}
RegExp 构造函数属性
主要属性
| 全 名 | 简写 | 说明 |
|---|---|---|
| input | $_ | 最后搜索的字符串(非标准特性) |
| lastMatch | $& | 最后匹配的文本 |
| lastParen | $+ | 最后匹配的捕获组(非标准特性) |
| leftContext | $` | input 字符串中出现在 lastMatch 前面的文本 |
| rightContext | $' | input 字符串中出现在 lastMatch 后面的文本 |
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
}
/*
* 注意: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.
9 来访问,分别包含第 1~9 个捕获组的匹配项。
let text = "this has been a short summer";
// ...表示字符占位 有多少个点 就可以代表几个字符
let pattern = /(..)or(.....)m(.)/g;
if (pattern.test(text)) {
console.log(RegExp.$1); // sh
console.log(RegExp.$2); // t sum
console.log(RegExp.$3); // e
}