正则表达式往往可以应用于定制化的表单校验,HTML自带的标签往往难以满足实际的需求。
正则表达式是一种Js复杂类型。
- 初识正则表达式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="">
<input type="text" required id="myText">
</form>
<script>
// 定义方式一:字面量
let reg = /abc/
console.log(reg)
// 定义方式二:内置构造函数
let reg2 = new RegExp("abc")
console.log(reg2)
let myText = document.querySelector("#myText")
myText.onblur = function () {
reg.test(myText.value)
}
</script>
</body>
</html>
- 元字符-基本元字符\d \D \s \S \w \W . \
// 1 \d 表示一位数字0~9
let reg1 = /\d/ // 是否包含一位数字
console.log(reg1.test("abahdoahwdfoiaw")) // false
console.log(reg1.test("abbc1p1p")) // true
let reg2 = /\d\d/ // 是否包含两个位置挨着的数字
console.log(reg2.test("abbc1p1p")) // false
console.log(reg2.test("abbc11p1p")) // true
// 2 \D 一位非数字
let reg3 = /\D/ // 是否包含一位非数字
console.log(reg3.test("1234648746431")) // false
console.log(reg3.test("aa121")) // true
let reg4 = /\Dk\D/
console.log(reg4.test("!kQpppp")) // true
console.log(reg4.test("kk222")) // false
// 3 \s 1位空白 (空白 缩进 换行)
let reg5 = /\s/
console.log(reg5.test("!kQpppp")) // false
console.log(reg5.test("!kQp ppp")) // true
console.log(reg5.test("!k\tQpppp")) // true
console.log(reg5.test("!k\nQpppp")) // true
// 4 \S 1位非空白
let reg6 = /\S\S\S/
console.log(reg6.test("p p p p")) // false
console.log(reg6.test("\"qwe p2\"")) // true
console.log(reg6.test("\n\n\t\t")) // false
// 5 \w 字母 数字 下划线
let reg7 = /\w/
console.log(reg7.test("**&&!!@@##")) // false
console.log(reg7.test("_**&&!!@@##")) // true
console.log(reg7.test("1**&&!!@@##")) // true
console.log(reg7.test("a**&&!!@@##")) // true
// 6 \W 非(字母 数字 下划线)
let reg8 = /\W/
console.log(reg8.test("*&^%___")) // true
console.log(reg8.test('*&^%')) // true
console.log(reg8.test('123456qqwasd')) // false
// 7 . 任意内容(不包含换行)
let reg9 = /./
console.log(reg9.test("..11")) // true
console.log(reg9.test("\n\n\n")) // false
// 8 \转义字符
let reg10 = /\d\.\d/ // 包含数字.数字
console.log(reg10.test("10.2")) // true
console.log(reg10.test("1.2")) // true
console.log(reg10.test("1@2")) // false
console.log(reg10.test("!!2")) // false
- 元字符-边界符^与$
// ^ 以...开头
let reg = /^\d/
console.log(reg.test("1popopo-+")) // true
console.log(reg.test("popopo-+")) // false
// $ 结尾边界
let reg2 = /\d$/
console.log(reg2.test("123456456!!!")) // false
console.log(reg2.test("!!!!!!!!qwqwq2")) // true
// 组合使用
let reg3 = /^abc$/
console.log(reg3.test("abcabc")) // true
console.log(reg3.test("abc")) // true
console.log(reg3.test("abcd")) // false
let reg4 = /^a\dc$/
console.log(reg4.test("a2c")) // true
console.log(reg4.test("a2c12")) // false
- 元字符-限定符 * + ? {n} {n,} {n, m}
// 1. * 0~多次
let reg1 = /\d*/
console.log(reg1.test("abc")) // true
console.log(reg1.test("abc1")) // true
console.log(reg1.test("abc12")) // true
// 2. + 1~多次
let reg2 = /\d+/
console.log(reg2.test("abc")) // false
console.log(reg2.test("abc1")) // true
console.log(reg2.test("abc12")) // true
console.log(reg2.exec("abc1234vvn")) // ['1234', index: 3, input: 'abc1234vvn', groups: undefined]
// 3. ? 0~1次
let reg3 = /\d?/
console.log(reg3.test("abc")) // true
console.log(reg3.test("ab1")) // true
console.log(reg3.test("ab123a123")) // true
console.log(reg3.test("123")) // true
// 4. {n}指定次数
let reg4 = /\d{4}/ // 包含连续四个数字
console.log(reg4.test("123145")) // true
console.log(reg4.test("123pppa1")) // false
console.log(reg4.test("asdada")) // false
let reg5 = /w{3}/
console.log(reg5.test("123145www")) // true
console.log(reg5.test("123pppa1")) // false
console.log(reg5.test("asdada")) // false
// 5. {n,} 大于等于n次
let reg6 = /\d{3,}/
console.log(reg6.test("66454866")) // true
console.log(reg6.exec("66454866")) // "66454866"
console.log(reg6.test("624")) // true
console.log(reg6.test("www78w5")) // false
// 6. {n,m} n~m次
let reg7 = /\d{2,4}/
console.log(reg7.test("1")) // false
console.log(reg7.test("1a1a1a")) // false
console.log(reg7.test("123456")) // true
console.log(reg7.exec("123456")) // 1234
// 注意
let reg8 = /c{2}/ // 表示c出现2次
let reg9 = /abc{2}/ // 表示前面是ab,后面紧挨着的c出现2次
console.log(reg9.test("123abcc")) // true
console.log(reg9.test("123abcabc")) // false
- 元字符-特殊符号 () | [] - [^]
// 1. () 作为整体
let reg1 = /^(abc){2}$/
console.log(reg1.test("abcabc")) // true
console.log(reg1.test("abc321abc")) // false
// 2. | 或 左边或右边的整体
let reg2 = /a|b|d/
console.log(reg2.test("eee")) // false
console.log(reg2.test("eed")) // true
console.log(reg2.test("aed")) // true
let reg3 = /abc|def|xyz/ // abc或者def或者xyz
console.log(reg3.test("abcef")) // true
console.log(reg3.test("abdef")) // true
console.log(reg3.test("abc")) // true
console.log(reg3.test("def")) // true
console.log(reg3.test("xyz")) // true
// 3. []代表1个
let reg4 = /[abcdef]/ // 表示这位在[abcdef]里吗
console.log(reg4.test("x")) // false
console.log(reg4.test("xa")) // true
console.log(reg4.test("xyz")) // false
let reg5 = /[abc]{3,5}/
console.log(reg5.test("a")) // false
console.log(reg5.test("aaa")) // true
// -
let reg6 = /[a-wA-Z0-9_]/
console.log(reg6.test("8")) // true
console.log(reg6.test("?")) // false
// [0-9] 相当于\d
// [0-9a-zA-Z_] 相当于\w
// 写在中括号内的^表示取反
let reg7 = /[^abc]/
console.log(reg7.test("a")) // false
console.log(reg7.test("bc")) // false
console.log(reg7.test("xxxa")) // true
- 捕获-exec和标识符i和g
// exec() 捕获片段
let reg1 = /\d/
console.log(reg1.exec("aaa")) // null
console.log(reg1.exec("aaa123aa")) // ['1', index: 3, input: 'aaa123aa', groups: undefined]
// 小案例
let dataStr = "time is from 2023-01-01 12:20:12 to 2026-11-01 12:26:25"
let reg2 = /\d{4}-\d{1,2}-\d{1,2}/
let newStr = reg2.exec(dataStr)[0] // 2023-01-01 (懒惰性)
let newDataStr = newStr.split('-').join('/')
console.log(newDataStr) // 2023/01/01
// 标识符 g(全局global) i(忽略大小写ignore)
console.log("======不加()的全局========")
let reg3 = /\d{4}-\d{1,2}-\d{1,2}/g
// 连续调用多次,可以全部捕获出来
while (true) {
let newStr2 = reg3.exec(dataStr)
if (newStr2 === null) {
break
}
console.log(newStr2)
}
console.log("======加()的全局========")
let reg4 = /(\d{4})-(\d{1,2})-(\d{1,2})/g
while (true) {
let newStr2 = reg4.exec(dataStr)
if (newStr2 === null) {
break
}
console.log(newStr2)
}
// i忽略大小写
console.log("====i忽略大小写=====")
let reg5 = /[a-z]/
console.log(reg5.exec("AAza")[0]) // z
let reg6 = /[a-z]/i
console.log(reg6.exec("AAza")[0]) // A
// 同时使用i和g的写法: /a-z/ig
- 正则表达式的两大特性--懒惰和贪婪
// 1. 懒惰性 : 解决方案 使用全局标识符g
// 2. 贪婪
let reg = /\d{1,4}/
console.log(reg.exec("aa1234bb")) // 1234
// 2. 非贪婪 加问号
let reg1 = /\d{1,4}?/
console.log(reg1.exec("aa1234bb")) // 1
/*
*?
+?
??
{n,}?
{n,m}?
*/
let str = `
<p class="active"><span>Alex</span></p>
`
// 想拿到<p class="active">
let reg3 = /<p.*?>/
console.log(reg3.exec(str))
- 正则与字符串方法
// 之前:正则.text(字符串) 正则.exec(字符串)
// 字符串.replace()、字符串.search、字符串.match()
let str = 'adearfa'
let newStr = str.replace('a',"?")
console.log(newStr) // ?dearfa
// replace
newStr = str.replace(/a/g,'?')
console.log(newStr) // ?de?rf?
// search 也可以传入正则
console.log(str.search(/a/)) // 0
// match 捕获内容
let dataStr = "time is from 2023-01-01 12:20:12 to 2026-11-01 12:26:25"
console.log(dataStr.match(/\d{4}-\d{1,2}-\d{1,2}/g)) // ['2023-01-01', '2026-11-01']
- 案例-密码强度验证
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.box {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
box-sizing: border-box;
margin: 50px auto;
padding: 20px;
width: 600px;
height: 200px;
border: 2px solid black;
}
.box input {
width: 560px;
height: 70px;
border: 2px solid black;
padding: 0 15px;
font-size: 24px;
}
.box .sign {
width: 160px;
height: 32px;
font-size: 24px;
line-height: 32px;
text-align: center;
color: white;
background-color: gray;
}
.box .sign:nth-of-type(1).active {
/* 这里优先级不够的话,会触发不了 */
background-color: red;
}
.box .sign:nth-of-type(2).active {
background-color: orange;
}
.box .sign:nth-of-type(3).active {
background-color: green;
}
</style>
</head>
<body>
<div class="box">
<input type="text">
<div class="sign weak">弱</div>
<div class="sign mid">中</div>
<div class="sign strong">强</div>
</div>
<script>
// 在开发中,常用的正则直接用FeHelper上现成的就行
// 案例:
let inputEl = document.querySelector("input[type=text]")
let reg1 = /\d/
let reg2 = /[a-z]/i
let reg3 = /[!@#$%^&*()]/
let signs = document.querySelectorAll(".sign")
inputEl.addEventListener("input", (e) => {
let level = 0 // 满足正则的个数
if (reg1.test(e.target.value)) level++
if (reg2.test(e.target.value)) level++
if (reg3.test(e.target.value)) level++
for (let i = 0; i < signs.length; i++) {
signs[i].classList.remove("active")
if (i < level) {
signs[i].classList.add("active")
}
}
})
</script>
</body>
</html>