JS中的正则表达式

如何判断一个字符串符合特定的格式,或者抓取符合规则的字符串片段?

JS正则表达式写法

正则表达式(regular expression)描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。

总之,你可以用正则表达式规定一种格式,检测字符串是不是符合这个格式。

1
2
3
4
5
6
7
// 方式一:字面量写法,/内容/
let reg = /abc/

// 方式二:new一个,new RegExp("内容"),RegExp即Regular Expression
let reg = new RegExp("abc");

reg.test("字符串") //test方法可以判断字符串是否符合正则表达式,此处判断是否包含abc

一个输入校验的小案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="">
<input type="text" required id="mytext">
<input type="submit" value="submit">

</form>
<script>
let reg = /abc/;
mytext.onblur=function(){ //失去焦点时触发事件
console.log(mytext.value); //打印输入的值
console.log(reg.test(mytext.value)); //判断是否为abc
}
</script>
</body>
</html>

image-20230116180119408

元字符

正则表达式中一种特殊的字符,类似转义字符,能够表达一种类型的数据。

基本元字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//  \d 一位数字(0-9),判断是否包含至少一位数字,输入两个就判断是否包含至少两个数字
let reg = /\d/;
console.log(reg.test("12a3")); //true
console.log(reg.test("1")); //true
console.log(reg.test("abc")); //false

// \D 一位非数字,用法同上
let reg = /\D/
console.log(reg.test("12a3")); //true
console.log(reg.test("1")); //false
console.log(reg.test("abc")); //true

// \s 一位空白(空格,缩进,换行)
let reg = /\s/
console.log(reg.test("12a 3")); //true
console.log(reg.test("1\nbc")); //true
console.log(reg.test(" abc")); //true
console.log(reg.test("abc")); //false

// \S 一位空白(空格,缩进,换行)
let reg = /\S/
console.log(reg.test("")); //false
console.log(reg.test(" ")); //false
console.log(reg.test("\n\n")); //false
console.log(reg.test(" \nb "));//true

// \S 一位空白(空格,缩进,换行)
let reg = /\S/
console.log(reg.test("")); //false
console.log(reg.test(" ")); //false
console.log(reg.test("\n\n")); //false
console.log(reg.test(" \nb "));//true

// \w 一位字符(数字,字母,下划线)
let reg = /\w/
console.log(reg.test("#^&")); //false
console.log(reg.test(" a ")); //true
console.log(reg.test("1")); //true
console.log(reg.test("_"));//true
console.log(reg.test(" "));//false

// \W 一位非数字,字母,下划线
let reg = /\W/
console.log(reg.test("#^&")); //true
console.log(reg.test(" a ")); //true
console.log(reg.test("1")); //false
console.log(reg.test("_"));//false
console.log(reg.test(" "));//true

// . 任意内容(不包括换行符)
// 注意:要变成普通的点,用转义字符:/.
let reg = /./
console.log(reg.test("#^&")); //true
console.log(reg.test(" ")); //true
console.log(reg.test("1_a")); //true
console.log(reg.test("_\n")); //true
console.log(reg.test("\n\n")); //false

只用元字符表示包含,只要有,就能通过判断

边界符

边界符用来修饰基本元字符或普通字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ^	开头限制
let reg = /^\d/ //开头必须是数字
console.log(reg.test("8skj")); //true
console.log(reg.test("a5156")); //false
console.log(reg.test(" 5a56")); //false
// $ 结尾限制
let reg = /\w$/ //结尾必须是数字字母下划线
console.log(reg.test("8skj ")); //false
console.log(reg.test("a5156%#¥")); //false
console.log(reg.test(" 5a56_")); //true

//注意:当两者连用时
let reg = /^abcde$/
//表示以a开头,以e结尾,而a和e的中间为bcd,因此只能匹配abcde
console.log(reg.test("abcde")); //true
console.log(reg.test("abcdeabcde")); //false
console.log(reg.test("abcdejiolabcde")); //false

限定符

限定符用来修饰基本元字符或普通字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// *	限定0或多个
let reg = /\d*/ //包含任意个数字

// + 限定1个或多个
let reg = /\d+/ //至少包含一个数字

// ? 限定0或1个
let reg = /\d?/ //只有零个或者一个

// {n} 限定有n个连续数字
let reg = /\d{6}/ //包含6个连续数字

// {n,} 限定至少n个连续数字看,>=n
let reg = /\d{5,}/ //五个及以上数字

// {n,m} n个到m个
let reg = /\d{5,8}/ //至少五个,最多八个数字都能匹配

注意,上面的边界符合限定符只能修饰一个字符!

特殊符号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ()	将多个字符作为一个整体,这样就能修饰多个元字符
let reg = /^(abc){2}$/ //只能匹配abcabc

// | 或
let reg = /a|b/ //包含a或者b
//注意:或修饰的是整体,而不是单个字符
let reg = /abc|11568|@qq.com/ //包含abc或者11568或者@qq.com

// [] 包含其中的一个字符
let reg = /[abcde]/ //只要包含abcde中的一个字母,就能匹配
let reg = /[abcde]{3,t}/ //至少三个,最多五个字母在这里面,adc能匹配,acxyz不能匹配

// [a-z] [0-9] [A-Z]
// [a-zA-Z0-9_] a到z,A到Z,0-9的简写,这个表达式就是/w

// [^ ] 包含一个不在其中的字符
let reg = /[^abcde]/ //只要包含abcde中的一个字母,就不能匹配

exec方法

前面说过reg.test("字符串") 可以判断是否匹配

reg.exec("字符串") 可以从一段字符串中,将匹配的部分字符串取出返回(返回值为一个数组)

1
2
3
4
5
6
7
8
9
10
11
12
13
let reg = /\d{4}-\d{1,2}-\d{1,2}/ 
console.log(reg.exec("This time is 2077-1-17 12:37:44"));
//返回一个数组,数组0号位为,2077-1-17
//但是不能匹配多个日期,只能获取第一个遇到的日期片段

//如果加小括号,里面的内容单独捕获一遍
let reg = /(\d{4})-(\d{1,2})-(\d{1,2})/
console.log(reg.exec("This time is 2077-1-17 12:37:44"));
//结果如下
0: "2077-1-17" //0号位是整个字符串
1: "2077" //1号位开始一次是小括号里的内容
2: "1"
3: "17"

标识符

全局标识符g,可以让系统记住上次查找到哪个位置了,下一次接着找

1
2
3
4
5
6
//	g	全局标识符
let reg = /\d{4}-\d{1,2}-\d{1,2}/g //在正则表达式后面加上g
console.log(reg.exec("This time is 2077-1-17 12:37:44,not 1977-8-18 01:23:44"));
//第一次调用exec方法,返回2077-1-17
console.log(reg.exec("This time is 2077-1-17 12:37:44,not 1977-8-18 01:23:44"));
//第二次调用exec方法,返回1977-8-18

i标识符,自动忽略大小写

1
2
3
4
//	i	忽略大小写
let reg = /abc/i
console.log(reg.test("aBcdjf")); //true
console.log(reg.exec("AbCdjf")[0]); //AbC

正则表达式的两大特性

懒惰性

前面说过,正则默认检索完一次字符串后,第二次从头检索。

解决:用全局标识符g

贪婪性

当我们正则规定了一个范围后,默认寻找符合的最长的字符串

解决: 用?进入非贪婪模式,匹配符合的最短字符串

比如

1
2
3
4
//对字符串	<p class="active"><span></span></p>	只匹配一个<p 属性>
//如果用 reg=/<p.*>/ ,会把整个字符串匹配下来,因此可以用?将*转化为非贪婪模式
let reg=/<p.*?>/;
console.log(reg.exec('<p class="active"><span></span></p>')[0]); //返回<p class="active">

正则与字符串方法连用

str.replace(目标字符串,替换内容) 目标字符串处可以用正则表达式

1
2
3
4
5
6
7
let str = 'abbacdako'
let newstr = str.replace("a","$"); //replace方法不改变远字符串,返回一个新字符串
console.log(newstr); // 返回$bbacdako,只替换第一个找到的a

let str = 'abbacdako'
let newstr = str.replace(/a/g,"$"); //replace方法第一个参数用正则表达式,添加全局标识符
console.log(newstr); // 所有a替换为了$,效果同replaceAll方法

str.search(目标字符串) 目标字符串可以用正则

1
2
3
4
5
let str = 'abbacdako'
console.log(str.search("ba")); // 2,返回第一个符合条件字符串索引位置,找不到返回-1

let str = 'a3ildfjl56ii'
console.log(str.search(/\di/)); // 找到3i符合条件,返回1

str.match(目标字符串) 目标字符串可以用正则

1
2
3
4
5
let str = 'This time is 2077-1-17 12:37:44,not 1977-8-18 01:23:44'
console.log(str.match(/\d{4}-\d{1,2}-\d{1,2}/g)); // 匹配所有符合正则的字符串,返回一个数组

0: "2077-1-17"
1: "1977-8-18"