一、概述
正则表达式(Regular_Expressions)用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象。这些模式被用于 RegExp 的 exec 和 test 方法, 以及 String 的 match、matchAll、replace、search 和 split 方法。
简单的说,就是按照某种规则去匹配符合条件的字符串。
二、创建正则表达式
新建正则表达式有两种方法。一种是使用字面量,以斜杠表示开始和结束;另一种是使用RegExp构造函数。
// 1、使用字面量:编译时创建
var r1 = /CHINA/;
// 2、使用RegExp构造函数:运行时创建
var r2 = new RegExp("CHINA");
正则表达式还可以接受第二个参数,表示修饰符(详细解释见下文)。
var r1 = /CHINA/i;
var r2 = new RegExp("CHINA", "i");
正则对象生成以后,有两种使用方式:
- 正则对象的方法:将字符串作为参数,比如
regex.test(string)。- 字符串对象的方法:将正则对象作为参数,比如
string.match(regex)。
三、正则属性和方法
1、属性
正则对象的属性分成两类。
一类是修饰符相关,返回一个布尔值,表示对应的修饰符是否设置,ES6新增了y 修饰符与u修饰符。
- ignoreCase:返回一个布尔值,表示是否设置了i修饰符,用于 忽略大小写 ,该属性只读。
- global:返回一个布尔值,表示是否设置了g修饰符,用于 全局匹配 ,该属性只读。
- multiline:返回一个布尔值,表示是否设置了m修饰符,用于 多行模式匹配 ,该属性只读。
var r = /abc/igm;
r.ignoreCase // true
r.global // true
r.multiline // true
另一类是与修饰符无关的属性,主要是下面两个。
- lastIndex:返回下一次开始搜索的位置。该属性可读写,但是只在设置了
g修饰符时有意义。 - source:返回正则表达式的字符串形式(不包括反斜杠),该属性只读。
2、方法
2.1、test() *
正则对象的test方法返回一个布尔值,表示当前模式是否能匹配参数字符串。
// 1、检测字符串是否包含‘@’
/@/.test('lihy_online@163.com'); // true
// 2、检测字符串是否包含‘@’
/@/.test("Nothing's gonna change my love for you.") // false
如果正则表达式带有g 修饰符,则每一次test方法都从上一次结束的位置开始向后匹配。
var reg = /n/g;
reg.lastIndex
0
reg.test("morning");
true
reg.lastIndex
4
reg.test("morning");
true
reg.lastIndex
6
reg.test("morning");
false
reg.lastIndex
0
上面代码的正则对象使用了 g 修饰符,表示要记录搜索位置。接着,三次使用test方法,每一次开始搜索的位置都是上一次匹配的后一个位置。带有 g 修饰符时,可以通过正则对象的 lastIndex 属性指定开始搜索的位置。
var reg = /n/g;
reg.lastIndex = 6;
reg.test("morning");
false
上面代码指定从字符串的第6个位置开始搜索,这个位置后面是没有字符 n 的,所以返回 false。
lastIndex 属性只对同一个正则表达式有效,所以下面这样写是错误的。
var count = 0;
while (/a/g.test('blablabla')) {
count++;
}
上面代码会导致无限循环,因为 while 循环的每次匹配条件都是一个新的正则表达式,导致 lastIndex 属性总是等于0。
如果正则模式是一个空字符串,则匹配所有字符串。
new RegExp('').test('abc') // true
2.2、exec()
正则对象的 exec 方法,可以返回匹配结果。如果发现匹配,就返回一个数组,成员是每一个匹配成功的子字符串,否则返回 null。
请看示例:
四、字符串对象的方法
字符串对象的方法之中,有4种与正则对象有关。
-
match():返回一个数组,成员是所有匹配的子字符串。"Hello".match(/l/g); (2) ['l', 'l'] -
search():按照给定的正则表达式进行搜索,返回一个整数,表示匹配开始的位置。"曾经沧海难为水,留取丹心照汗青。".search(/沧海/); 2 -
replace():按照给定的正则表达式进行替换,返回替换后的字符串。"来咯,来咯,真嘞来咯!".replace(/来咯/, "走咯"); "走咯,来咯,真嘞来咯!" "来咯,来咯,真嘞来咯!".replace(/来咯/g, "走咯"); "走咯,走咯,真嘞走咯!"replace 方法的第二个参数可以使用美元符号
$,用来指代所替换的内容。- $&:指代匹配的子字符串。
- $`:指代匹配结果前面的文本。
- $' :指代匹配结果后面的文本。
- $n:指代匹配成功的第n组内容,n是从1开始的自然数。
- $$:指代美元符号*$*。
// 1、$&:指代匹配的子字符串。 "ABC".replace(/B/, '-$&-'); 'A-B-C' // 2、$`:指代匹配结果前面的文本。 "ABC".replace(/B/, '$`'); 'AAC' // 3、$' :指代匹配结果后面的文本。 "ABC".replace(/B/, "$'"); 'ACC' // 4、$n:指代匹配成功的第n组内容,n是从1开始的自然数。 "17398888669".replace(/(\d{3})(\d{4})(\d{4})/, "$1 *** $3"); '173 *** 8669' // 5、$$:指代美元符号$。 "ABC".replace(/B/, "$$"); 'A$C' -
split():按照给定规则进行字符串分割,返回一个数组,包含分割后的各个成员。"A-B-C".split('-'); (3) ['A', 'B', 'C']
五、匹配规则 *
正则表达式对字符串的匹配有很复杂的规则。下面一一介绍这些规则。
01. 字面量字符
字面意义,如 /muzili/ ,匹配的就是字符串 muzili。
02. 元字符
| 字符 | 描述 | |||
|---|---|---|---|---|
. | 表示除换行、回车之外的所有字符 | |||
^ | 表示字符串的开始位置 | |||
$ | 表示字符串的结束位置 | |||
| ` | ` | 选择符,如 `x | y表示匹配x 或y ,比如:火锅 | 烧烤` 表示匹配 火锅 或 烧烤 |
\ | 转义字符,用于匹配一些特殊字符本身,比如要匹配字符+,你应该使用 \+ 表示 |
03. 量词符
模式的精确匹配次数,使用大括号({})表示。
| 字符 | 描述 |
|---|---|
{n} | 表示指定字符重复n次 |
{n,} | 表示指定字符至少重复n次 |
{n,m} | 表示指定字符重复不少于n次,不多于m次 |
* | 量词符:表示某个模式出现0次或多次,等同于{0,} |
+ | 量词符:表示某个模式出现1次或多次,等同于{1,} |
? | 量词符:表示某个模式出现0次或1次, 等同于{0,1} |
04. 特殊字符
| 字符 | 含义 |
|---|---|
\t | 水平制表符 |
\v | 垂直制表符 |
\n | 换行符 |
\r | 回车符 |
\0 | 空字符 |
\f | 换页符 |
\cX | 控制字符,与X对应的控制字符(Ctrl + X) |
05. 字符类
表示符合某种特性的字符类别,使用 [] 表示
| 字符 | 描述 |
|---|---|
[xyz] | 表示匹配x、y、z中的任意一个字符 |
[^xyz] | 表示字符串中只有模式中的字符时,才返回false |
[^] | 表示匹配任意字符 |
[0-9] | 连字符,表示匹配0~9之间的任意字符,也可用于表示字母,比如[A-Z] |
tips:字符类的连字符必须在头尾两个字符中间,才有特殊含义,否则就是字面含义。比如,
[-9]就表示匹配连字符和9,而不是匹配0到9。
06. 预定义模式
预定义模式指的是某些常见模式的简写方式。
| 字符 | 描述 |
|---|---|
\d | 匹配0-9之间的任一数字,相当于[0-9] |
\D | 匹配所有0-9以外的字符,相当于[^0-9] |
\w | 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_] |
\W | 除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_] |
\s | 匹配空格(包括制表符、空格符、断行符等),相等于[\t\r\n\v\f] |
\S | 匹配非空格的字符,相当于[^\t\r\n\v\f] |
\b | 匹配词的边界,即该次必须独立存在,如:/\bhello/.test("hello world") 为true |
\B | 匹配非词边界,即在词的内部 |
07. 贪婪模式 & 非贪婪模式
- 贪婪模式:尽可能多匹配(默认)
- 非贪婪模式:尽可能少匹配
贪婪模式转非贪婪模式在量词符后加上?即可。
/\d+/.exec("123");
// => ["123", index: 0, input: "123", groups: undefined]
/\d+?/.exec("123");
// => ["1", index: 0, input: "123", groups: undefined]
08. 修饰符
修饰符(modifier)表示模式的附加规则,放在正则模式的最尾部。
g:全局匹配 *i:忽略大小写 *m:多行模式
09. 组匹配
| 字符 | 描述 |
|---|---|
(x) | 捕获组 模式 /(foo) (bar) \1 \2/ 中的 '(foo)' 和 '(bar)' 匹配并记住字符串 "foo bar foo bar" 中前两个单词。模式中的 \1 和 \2 表示第一个和第二个被捕获括号匹配的子字符串,即 foo 和 bar,匹配了原字符串中的后两个单词。注意 \1、\2、...、\n 是用在正则表达式的匹配环节。而在正则表达式的替换环节,则要使用像 $1、$2、...、$n 这样的语法,例如,"17398888669".replace(/(\d{3})(\d{4})(\d{3})/, "$1****$3")。$& 表示整个用于匹配的原字符串。 |
(?:x) | 非捕获组:表示不返回该组匹配的内容,即匹配的结果中不计入这个括号。 非捕获组的作用请考虑这样一个场景,假定需要匹配 a或者aa,正则表达式就应该写成/(a){1,2}/,但是这样会占用一个组匹配。这时,就可以使用非捕获组,将正则表达式改为/(?:a){1,2}/,它的作用与前一个正则是一样的,但是不会单独输出括号内部的内容 |
x(?=y) | 先行断言:x只有在y前面才匹配,y不会被计入返回结果。比如,要匹配后面跟着百分号的数字,可以写成/\d+(?=%)/。 |
x(?!y) | 先行否定断言:x只有不在y前面才匹配,y不会被计入返回结果。比如,要匹配后面跟的不是百分号的数字,就要写成/\d+(?!%)/。 |
六、附:常用正则表达式
点击前往 史上最全常用正则表达式