Web APIs第七天-正则表达式

1. 正则表达式

  1. 正则表达式(Regular Expression)是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象
  2. 通常用来查找、替换那些符合正则表达式的文本,许多语言都支持正则表达式

正则表达式在 JavaScript中的使用场景:

  1. 例如验证表单:用户名表单只能输入英文字母、数字或者下划线, 昵称输入框中可以输入中文(匹配)
  2. 比如用户名: /^[a-z0-9_-]{3,16}$/
  3. 过滤掉页面内容中的一些敏感词(替换),或从字符串中获取我们想要的特定部分(提取)等
  4. 正则表达式是用于匹配字符串中字符组合的模式
  5. .正则表达式作用: 表单验证(匹配),、过滤敏感词(替换)、字符串中提取我们想要的部分(提取)

2. 定义正则表达式语法:

  1. 定义规则
  2. 查找

JavaScript 中定义正则表达式的语法有两种,我们先学习其中比较简单的方法:

1
2
3
其中 / /是正则表达式字面量
// 1. 定义规则/正则表达式 存的是对象
let reg = /前端/

3. 判断是否有符合规则的字符串

1. test() 方法 用来查看正则表达式与指定的字符串是否匹配

  1. 定义正则表达式, 检测查找是否匹配
  2. 如果正则表达式与指定的字符串匹配 ,返回true,否则false
1
2
3
// 查找 检测是否匹配 返回true/false 重点
let num1 = '努力学前端'
console.log(reg.test(num1))

2. 检索(查找)符合规则的字符串:

  1. exec() 方法 在一个指定字符串中执行一个搜索匹配
  2. 如果匹配成功,exec() 方法返回一个数组,否则返回null
1
2
3
// 检索/查找 符合规则的字符串 返回的数组
let num2 = reg.exec(num1)
console.log(num2)

正则表达式检测查找 test方法和exec方法的区别

  1. test方法 用于判断是否有符合规则的字符串,返回的是布尔值 找到返回 true,否则false
  2. exec方法用于检索(查找)符合规则的字符串,找到返回数组,否则为 null

4. 元字符

  1. 是一些具有特殊含义的字符,可以极大提高了灵活性和强大的匹配功能, 比如,规定用户只能输入英文26个英文字母,普通字符的话 abcdefghijklm….., 但是换成元字符写法: [a-z]
  2. MDN文档: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions
  3. 正则测试工具: http://tool.oschina.net/regex

1. 边界符

  1. 正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符

  2. 如果 ^ 和 $ 在一起,表示必须是精确匹配

边界符说明
^匹配行首的文本**(以谁开始)**
$匹配行尾的文本**(以谁结束)**
1
2
3
4
5
6
// 1. ^开头
console.log(/^哈哈/.test('都哈哈')) // false
console.log(/^哈哈/.test('哈哈大笑')) // true
// 2. $ 结尾 精确匹配
console.log(/^哈哈$/.test('哈哈你们')) // false
console.log(/^哈哈$/.test('哈哈')) // true

2. 量词

  1. 量词用来 设定某个模式出现的次数
  2. 注意: 逗号左右两侧千万不要出现空格
量词说明
*重复0次到N次 n >= 0
+只重复1次到N次 n >= 1
?只重复0次或1次
{n}只能出现n次
{n,}出现n次或更多次 >= n
{n,m}大于N次 小于M次 >= n <= m 注意不能空格
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
// 1. * 重复0次到N次 n >= 0
console.log(/a*/.test(''))
console.log(/a*/.test('aa'))
console.log(/a*/.test('aaaa'))
console.log(/a*/.test('b'))
// 2. + 只重复1次到N次 n >= 1
console.log(/a+/.test(''))
console.log(/a+/.test('a'))
console.log(/a+/.test('aaa'))
console.log(/a+/.test('b'))
// 3. ? 只重复0次或1次
console.log(/^a?$/.test('a'))
console.log(/^a?$/.test('aa'))
console.log(/^a?$/.test('aaaaa'))
console.log('----------')
// 4. {3} 只能出现n次
console.log(/^a{3}$/.test('aa'))
console.log(/^a{3}$/.test('aaa'))
console.log(/^a{3}$/.test('aaaa'))
// 5. {3, } 出现n次或更多次 >= n
console.log(/^a{3,}$/.test('aa'))
console.log(/^a{3,}$/.test('aaa'))
console.log(/^a{3,}$/.test('aaaa'))
// 6. {3,6} 大于N次 小于M次 >= n <= m 注意不能空格
console.log(/^a{3,6}$/.test('aa'))
console.log(/^a{3,6}$/.test('aaa'))
console.log(/^a{3,6}$/.test('aaaa'))
console.log(/^a{3,6}$/.test('aaaaaaa'))

3.字符类

  1. 匹配字符集合, 后面的字符串只要包含 abc 中任意一个字符,都返回 true
  2. 里面加上 - 连字符, 使用连字符 - 表示一个范围
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
// 1. 只要包含abc任意一个 都是true
console.log(/[abc]/.test(''))
console.log(/[abc]/.test('ab'))
console.log(/[abc]/.test('admin'))
console.log(/[abc]/.test('csy'))
// 2. 连字符 只能选取一个
console.log(/^[abc]$/.test('abc'))
console.log(/^[abc]$/.test('a'))
console.log(/^[abc]$/.test('b'))
console.log(/^[abc]$/.test('c'))
console.log(/^[abc]$/.test('aa'))
// 3. 26个字母选取任意一个
console.log(/^[a-z]$/.test('d'))
console.log(/^[a-z]$/.test('e'))
console.log(/^[a-z]$/.test('f'))
console.log(/^[a-z]$/.test('F'))
// 4. 26个字符 包含大小写
console.log(/^[a-zA-Z]$/.test('Z'))
console.log(/^[a-zA-Z]$/.test('D'))
// 5. 26个字母 包含大小写和数字
console.log(/^[a-zA-Z0-9]$/.test('8'))
console.log(/^[a-zA-Z0-9]$/.test('9'))
// 6. 只能字母数字下划线
console.log(/^[a-zA-Z0-9-_]$/.test('1'))
// 7. {4,} 只对前面一个生效
console.log(/^[1-9][0-9]{4,}$/.test('10000'))
// 8. [^] 取反符号 除了小写字母以外的字符
console.log(/[^a-z]/.test('a'))
console.log(/[^a-z]/.test('A'))
// 9. . 匹配换行符之外 任何单个字符
console.log(/[.a]/.test('a'))
// 10. 日期格式
console.log(/^\d{4}-\d{1,2}-\d{1,2}/.test('20230102'))

4. 用户名验证案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 用户名要求用户英文字母,数字,下划线或者短横线组成,并且用户名长度为 6~16位
<input type="text">
<span></span>
let n1 = document.querySelector('input')
let n2 = document.querySelector('span')
n1.addEventListener('blur', function () {
if (/^[a-zA-Z0-9]{6,16}$/.test(n1.value)) {
n2.className = 'right'
n2.innerHTML = `输入正确`
} else {
n2.className = 'error'
n2.innerHTML = '请输入6~16的字符'
}
})

5. 字符类预定类:

预定义: 指的是某些常见模式的简写方式

1
2
// 日期格式
console.log(/^\d{4}-\d{1,2}-\d{1,2}/.test('20230102'))
预定类说明
\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]

6. 修饰符

  1. 修饰符约束正则执行的某些细节行为,如是否区分大小写、是否支持多行匹配等
  2. i 是单词 ignore 的缩写,正则匹配时字母不区分大小写
  3. g 是单词 global 的缩写,匹配所有满足正则表达式的结果
  4. replace 敏感词替换 搭配 g 使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 1. i 不区分大小写
console.log(/a/i.test('a'))
console.log(/a/i.test('A'))

// 2. g 选出所有满足表达式的结果
// 3. replace 敏感词替换 搭配 g 使用
<textarea name="" cols="30" rows="10"></textarea>
<button>发布</button>
<div></div>
<input type="text">
let n1 = document.querySelector('textarea')
let n2 = document.querySelector('button')
let n3 = document.querySelector('div')
n2.addEventListener('click', function () {
// n3.innerHTML = n1.value
// replace 敏感词替换 搭配 g全局替换 使用
n3.innerHTML = n1.value.replace(/你好|你哈/g, ('**'))
})

5. 综合案例

1
2
3
4
5
6
7
// 1. change 事件 当表单发生变化时触发 和blur不一样
let num1 = document.querySelector('input')
// 2. input 事件 输入就触发
// 3. change 事件 离开表单才触发 并且值得有变化
num1.addEventListener('change', function () {
console.log(1)
})
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// 1. 发送验证码 用户点5秒后重新获取验证码 立即执行函数
(function () {
let btnMsg = document.querySelector('.code')
btnMsg.addEventListener('click', function () {
let num1 = 5
this.innerHTML = '05秒后重新获取'
let time = setInterval(function () {
num1--
btnMsg.innerHTML = `0${num1}秒后重新获取`
if (num1 == 0) {
btnMsg.innerHTML = '发送验证码'
clearInterval(time)
}
}, 1000)
})
// 2. 用户名验证
let user = document.querySelector('[name=username]')
user.addEventListener('change', verify)
// *鼠标离开 下一步都需要表单验证 所以封装成函数
function verify() {
let reg = /^[a-zA-Z0-9-_]{6,16}$/
let span = user.nextElementSibling
if (!reg.test(user.value)) {
span.innerHTML = '请输入6~16的字符'
// *如果是false 则返回false/true 为下一步按钮做判断
return false
}
span.innerHTML = ''
return true
}
// 3. 手机号验证
let phone = document.querySelector('[name=phone]')
phone.addEventListener('change', verifyphone)
function verifyphone() {
// *11位手机号验证 正则表达式
let reg = /^1(3\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\d|9[0-35-9])\d{8}$/
let span = phone.nextElementSibling
if (!reg.test(phone.value)) {
span.innerHTML = '请输入11位的手机号'
return false
}
span.innerHTML = ''
return true
}
// 4. 验证码验证
let code = document.querySelector('[name=code]')
code.addEventListener('change', verifycode)
function verifycode() {
// *6位数验证码验证 正则表达式
let reg = /^\d{6}$/
let span = code.nextElementSibling
if (!reg.test(code.value)) {
span.innerHTML = '请输入6位数的验证码'
return false
}
span.innerHTML = ''
return true
}
// 5. 密码验证
let password = document.querySelector('[name=password]')
password.addEventListener('change', verifypassword)
function verifypassword() {
// *6~20位密码验证 正则表达式
let reg = /^[a-zA-Z0-9-_]{6,20}$/
let span = password.nextElementSibling
if (!reg.test(password.value)) {
span.innerHTML = '请输入6~20位密码'
return false
}
span.innerHTML = ''
return true
}
// 6. 再次密码验证
let pass = document.querySelector('[name=confirm]')
pass.addEventListener('change', verifypass)
function verifypass() {
let span = pass.nextElementSibling
if (pass.value !== password.value) {
span.innerHTML = '两次密码不一致'
return false
}
span.innerHTML = ''
return true
}
// 7. 同意按钮样式切换 queren2选中样式
let btnIocn = document.querySelector('.icon-queren')
btnIocn.addEventListener('click', function () {
this.classList.toggle('icon-queren2')
})
// 8. 提交按钮模块
let form = document.querySelector('form')
form.addEventListener('submit', function (e) {
// *如果 返回的false就不执行了 所以使用 !false就是 true
if (!verify()) {
// *preventDefault 阻止默认行为
e.preventDefault()
}
if (!verifyphone()) {
e.preventDefault()
}
if (!verifycode()) {
e.preventDefault()
}
if (!verifypassword()) {
e.preventDefault()
}
if (!verifypass()) {
e.preventDefault()
}
// 9. 勾选模块
// *contains 看有没有包含类 有就true 没有就false
if (!btnIocn.classList.contains('icon-queren2')) {
alert('请勾选同意协议')
e.preventDefault()
}
})
}())
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
// 1. 登录复选框按钮 为false弹窗提示框 
let btn = document.querySelector('.dl')
let check = document.querySelector('.remember')
let username = document.querySelector('[name=username]')
let password = document.querySelector('[name=password]')
btn.addEventListener('click', function (e) {
// *阻止默认行为
e.preventDefault()
if (!check.checked) {
alert('请勾选协议')
return
}
// 2. 为true则记住用户名密码 存储到本地
let obj = {
username: username.value,
password: password.value
}
localStorage.setItem('name', JSON.stringify(obj))
// *跳转到主页
location.href = './index.html'
})
// 3. 为true则记住用户名密码 存储到本地
let obj = JSON.parse(localStorage.getItem('name'))
if (obj) {
username.value = obj.username
password.value = obj.password
check.checked = true
}
1
2
3
4
5
6
7
8
9
// 1. 如果本地存储有数据 则显示 你好xxx
// 否则 则显示 请先注册登录
let li = document.querySelector('.xtx_navs li:first-child a')
let obj = JSON.parse(localStorage.getItem('name'))
if (obj) {
li.innerHTML = `你好 ${obj.username}, 欢迎来到小兔鲜儿购物`
} else {
li.innerHTML = '请先注册登录'
}

本节单词:

  1. reg
  2. test
  3. exec
  4. replace
  5. change