JS 正则
作者说
此文档只是个人学习笔记,源学习视频请参考:正则表达式教学
GitHub 文件地址:Regular-expression
什么是正则表达式
可以先定义一个需求,点击过程完成二张图片的切换,也就是说,我们增添一个 img 标签,然后在 js 中获取此标签元素,接着给它绑定点击事件,最后在点击事件函数体内实现相关逻辑 – 其中 src 属性是字符串,调用其 indexOf 方法可以判断某字符串是否在其中,如果在其中那么返回对应的索引值,否则返回 -1
<!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>正则概述</title>
</head>
<body>
<img src="./resource/images/Girl.jpg" alt="">
<script>
var img = document.querySelector('img'); // 通过标签名称获取元素
img.onclick = function(){
console.log(this.src) // 打印该图片的 src 属性
// indexOf 字符串查找 -- 返回值是字符串首次出现的位置
if(this.src.indexOf('Girl.jpg') > 0){
this.src = './resource/images/Sky.jpg';
}else{
this.src = './resource/images/Girl.jpg';
}
};
</script>
</body>
</html>
JS 标准库中的正则对象
创建正则对象
此处还介绍一种正则对象的方法:test,通过调用此方法可以判断某字符串中是否符合某正则
<!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>正则对象</title>
</head>
<body>
<script>
var str1 = 'abc123cdf'
var str2 = 'abc12cdf'
// 定义一个正则(二种方法) -- 字面量形式和函数创建形式
var reg1 = /3/;
var reg2 = new RegExp('3')
// 调用正则的 test 方法 -- 用来判断某字符串中是否有符合该正则的子字符串
console.log(reg1.test(str1)) // 存在此字符串 -- 则返回 true
console.log(reg2.test(str2)) // 不存在此字符串 -- 则返回 false
</script>
</body>
</html>
匹配模式
此处还介绍一种 String 对象的方法:replace,通过调用此方法可以将字符串中符合某正则的子字符串替换成指定的字符串
<!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></title>
</head>
<body>
<script>
var str1 = 'A'
var str2 = 'babab'
// i 修饰符表示忽略查询过程中的大小写问题
var reg1 = /a/i; // 字母量声明正则对象时修饰符添加的位置
var reg2 = new RegExp('a', 'i') // 构造函数时修饰符添加的位置
// g 修饰符表示查询全部
var reg3 = /b/g; // 字面量声明正则对象时修饰符添加的位置
var reg4 = new RegExp('b', 'g') // 构造函数时修饰符添加的位置
console.log(reg1.test(str1)) // 存在此字符串 -- 则返回 true
console.log(reg2.test(str1)) // 存在此字符串 -- 则返回 true
// String 对象的 replace 方法返回值是一个新的字符串 -- 且符合全局替换规则
console.log(str2.replace(reg3, '*')) // *a*a*
console.log(str2.replace(reg4, '*')) // *a*a*
</script>
</body>
</html>
正则对象的方法
test 方法和 exec 方法
<!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>正则对象的方法</title>
</head>
<body>
<script>
var str = 'abc123cde';
var reg = /123/;
console.log(reg.test(str)) // 符合正则规则 -- 返回值布尔值 true
console.log(reg.exec(str)) // 符合正则规则 -- 符合一个数组 -- 数组里有查询到的字符串
</script>
</body>
</html>
String 对象的方法
search 方法、match 方法、replace 方法和 split 方法
<!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>String 对象的方法</title>
</head>
<body>
<script>
var str = 'abc123cde';
var reg = /c/g; // 全局匹配
// search 方法返回值是一个索引 -- 查询符合正则的字符串首次出现的位置
var a = str.search(reg)
console.log(a) // 2
// match 方法返回值是一个数组 -- 数组里是匹配的结果
var b = str.match(reg)
console.log(b) // ["c", "c"]
// replace 方法返回值是一个新的字符串 -- 第一个参数是 reg -- 第二个参数是修改后的字符串
var c = str.replace(reg, '*')
console.log(c) // ab*123*de
// split 方法返回值是一个列表 -- 根据某 reg 分割字符串
var d = str.split(reg)
console.log(d) // ["ab", "123", "de"]
</script>
</body>
</html>
几个重要的概念
子表达式
在正则表达式中,通过一对圆括号括起来的内容,我们称之为子表达式
捕获
在正则表达式中,子表达式匹配到相应的内容时,系统会自动捕获这个行为,然后将子表达式匹配到的内容放入系统的缓存区中,我们把这个过程称之为捕获
<!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>子表达式</title>
</head>
<body>
<script>
var str = '123';
// 子表达式 (\d) 表示匹配一个数字 -- 如下正则代表匹配三个数字
// 缓冲区 1 中存放的数据是 1 -- 缓冲区 2 中存放的数据是 2 -- 缓冲区 3 中存放的数据是 3
var reg = /(\d)(\d)(\d)/;
console.log(str.replace(reg, '***'))
</script>
</body>
</html>
反向引用
在正则表达式中,我们可以使用 \n (n > 0,n 为整数,代表系统中的缓存区编号)来获取缓存区的内容,我们把这个过程称为反向引用
<!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>子表达式</title>
</head>
<body>
<script>
var str = '1221';
// 反向引用子表达式缓存区内容
// \1 表示反向引用第一个缓存区的内容(1) -- \2 表示反向引用第一个缓存区的内容(2)
var reg = /(\d)(\d)\2\1/;
console.log(str.match(reg)) // 控制台输出匹配到的字符串
</script>
</body>
</html>
编写正则表达式
正则表达式组成
正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式,正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配
查什么(匹配符)
匹配符
- 匹配符 \d 匹配任何一个数字 – \D 匹配任何一个非数字
- 匹配符 \w 匹配任何字母数字和下划线 – \W 匹配任何一个非字母数字及下划线
- 匹配符 \s 匹配任何空字符 – \S 匹配任何一个非空字符
- 匹配符 . 匹配任何除回车之外的字符
<!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>匹配符</title>
</head>
<body>
<script>
var str1 = 'abc123cde';
// 匹配符 \d 匹配任何一个数字 -- \D 匹配任何一个非数字
var reg1 = /\d/;
console.log(str1.replace(reg1, '*')) // abc*23cde
var reg2 = /\D/;
console.log(str1.replace(reg2, '*')) // *bc123cde
var str2 = '_*'
// 匹配符 \w 匹配任何字母数字和下划线 -- \W 匹配任何一个非字母数字及下划线
var reg3 = /\w/;
console.log(str2.replace(reg3, '*')) // **
var reg4 = /\W/;
console.log(str2.replace(reg4, '*')) // _*
var str3 = ' 1'
// 匹配符 \s 匹配任何空字符 -- \S 匹配任何一个非空字符
var reg5 = /\s/;
console.log(str3.replace(reg5, '*')) // *1
var reg6 = /\S/;
console.log(str3.replace(reg6, '*')) // *
var str4 = '1'
// 匹配符 . 匹配任何除回车之外的字符
var reg7 = /./;
console.log(str4.replace(reg7, '*')) // *
</script>
</body>
</html>
匹配区间
- /[12]/ 表示匹配 1 或 2 字符
- /[a-z]/ 表示匹配 a 到 z 字符
- /[0-9]/ 表示匹配 0 到 9 字符
- /[^12]/ 表示匹配除 1 和 2 之外的字符
- /[\u4e00-\u9fa5]/ 表示匹配任意汉字
<!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>匹配区间</title>
</head>
<body>
<script>
var str1 = '123abcd';
// 表示匹配 1 或 2 字符
var reg1 = /[12]/;
console.log(str1.replace(reg1, '*')) // *23abcd
// 表示匹配 a 到 z 字符
var reg2 = /[a-z]/;
console.log(str1.replace(reg2, '*')) // 123*bcd
// 表示匹配 0 到 9 字符
var reg3 = /[0-9]/;
console.log(str1.replace(reg3, '*')) // *23abcd
// 脱字符 ^ 表示字符区间取反
// 表示匹配除 1 和 2 之外的字符
var reg4 = /[^12]/;
console.log(str1.replace(reg4, '*')) // 12*abcd
var str2 = '苏';
// 表示匹配任意汉字
var reg5 = /[\u4e00-\u9fa5]/;
console.log(str2.replace(reg5, '*')) // *
</script>
</body>
</html>
查多少(限定符)
限定符
- \d{m,n} ,\d 表示查询数字,m 表示至少查询 m 位数字,n 表示至多查询 n 位数字
- \d*,\d 表示查询数字,* 表示至少查询 1 位
- \d+,\d 表示查询数字,+ 表示至少查询 2 位
- \d?,\d 表示查询数字 ,? 表示只能查询 1 位或 2 位
<!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>查多少</title>
</head>
<body>
<script>
// 遵循贪婪查询原则 -- 原则上查询的位数越多越好
// 语法:\d{m,n} -- \d 表示查询数字 -- m 表示至少查询 m 位数字 -- n 表示至多查询 n 位数字
var str1 = '我的QQ号是:483517937 和 1314520521'
// 全局范围内查找第一位是数字 1 到 9 -- 至少含有 5 位数字 -- 至多含有 10 位数字的子字符串
var reg1 = /[1-9]\d{4,9}/g;
console.log(str1.match(reg1)) // ["483517937", "1314520521"]
/* 语法:\d* -- \d 表示查询数字 -- * 表示至少查询 1 位
\d+ -- \d 表示查询数字 -- + 表示至少查询 2 位
\d? -- \d 表示查询数字 -- ? 表示只能查询 1 位或 2 位
*/
var reg2 = /[1-9]\d*/g;
var reg3 = /[1-9]\d+/g;
var reg4 = /[1-9]\d?/g;
var str2 = '2a22'
console.log(str2.match(reg2)) // ["2", "22"]
console.log(str2.match(reg3)) // ["22"]
console.log(str1.match(reg4)) // ["48", "35", "17", "93", "7", "13", "14", "52", "52", "1"]
</script>
</body>
</html>
从哪查(定位符)
正则表达式只会到字符串去寻找是否有与之匹配的结果,如果有就认为是正确的,而不考虑其字符串本身是否合法,为了解决如上问题,出现了定位符,定位符可以将一个正则表达式固定在一行的开始或结束,也可以创建只在单词内或只在单词的开始或结尾处出现的正则表达式
<!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>从哪查</title>
</head>
<body>
<script>
// 单词的切分
var str1 = 'It is a cool dog.';
var reg1 = /\b\w+\b/g;
console.log(str1.match(reg1)) // 数组:0: "It" 1: "is" 2: "a" 3: "cool" 4: "dog"
// 字符串的识别 -- 我的目的是识别一个正确的 QQ 号
var str2 = 'q483517937q'
// 如果我们使用如下正则 -- 检测结果显然是错误的
var reg2 = /[1-9]\d{4,9}/;
console.log(str2.match(reg2)) // ["483517937", index: 1, input: "q483517937q", groups: undefined]
// 此处我们借用 ^ 和 $ 来判断字符串的首位和末位
// 如果我们使用如下正则 -- 检测结果是正确的
var reg3 = /^[1-9]\d{4,9}$/;
console.log(str2.match(reg3)) // null
</script>
</body>
</html>
转义字符
正则表达式中,(.、+、\ )等是属于表达式的一部分,但是我们在匹配的时候,字符串中也需要匹配这些特殊字符,所以我们必须使用反斜杠来对某些特殊字符进行转义
<!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>转义字符</title>
</head>
<body>
<script>
/* \w+ 匹配 http
: 匹配 :
\/\/ 匹配 //
\w+ 匹配 xiaosu
\. 匹配 .
\w+ 匹配 com
*/
var str = 'http://xiaosu.com'
var reg = /\w+:\/\/\w+\.\w+/;
console.log(str.match(reg)) // "http://xiaosu.com"
</script>
</body>
</html>
或者的用法
<!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>或者</title>
</head>
<body>
<script>
var str = 'agency,algebra,anxiety,apartment,argue';
var reg = /\ba(gency|lgebra|nxiety|rgue)\b/g;
console.log(str.match(reg)) // 数组:0: "agency" 1: "algebra" 2: "anxiety" 3: "argue"
</script>
</body>
</html>
预查
<!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>预查</title>
</head>
<body>
<script>
var str = 'When i am studying,he is reading'
// 需求:字符串中含有 ing 结尾的词根找出来
var reg1 = /\b\w+ing\b/g;
console.log(str.match(reg1)); // ["studying", "reading"]
// 正向预查 -- 正预测 -- 前瞻 -- 先行断言
var reg2 = /\b\w+(?=ing\b)/g;
console.log(str.match(reg2)); // ["study", "read"]
// 需求:字符串中不是以 ing 结尾的词找出来
// 负向预查 -- 负预测 -- 前瞻 -- 先行否定
var reg3 = /\b\w+(?!ing)\w{3}\b/g;
console.log(str.match(reg3)); // ["When"]
</script>
</body>
</html>
注册验证
<!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>注册验证</title>
<style>
input{
height: 20px;
width: 350px;
}
.hide{
display: none;
}
.inp_red{
border: 1px solid red;
}
.inp_green{
border: 1px solid green;
}
</style>
</head>
<body>
用户名:<br>
<input type="text" id="inp_name"><br>
<span class="hide" value=''></span><br>
邮箱:<br>
<input type="text" id="inp_email"><br>
<span class="hide"></span><br>
密码:<br>
<input type="text" id="inp_pwd"><br>
<span class="hide"></span><br>
重复密码:<br>
<input type="text" id="inp_re"><br>
<span class="hide"></span><br>
<button>提交</button>
<script>
var input_element = document.getElementsByTagName('input');
var span_element = document.getElementsByTagName('span');
function changeColor(id, color, txt){
this.className = 'inp_' + color;
span_element[id].className = '';
span_element[id].style.color = color;
span_element[id].innerHTML = txt;
}
for(var i=0;i<input_element.length;i++){
input_element[i].addEventListener('blur', function(){
if(this.id == 'inp_name'){
if(this.value == ''){
changeColor(0, 'red', '用户名不能为空')
}else if(this.value.length < 3){
changeColor(0, 'red', '用户名长度不够')
}else{
changeColor(0, 'green', '√')
}}
if(this.id == 'inp_email'){
var reg = /\w+@\w+\.\w{2,6}/;
if(this.value == ''){
changeColor(1, 'red', '邮箱不能为空')
}else if(!reg.test(this.value)){
changeColor(1, 'red', '邮箱格式不正确')
}else{
changeColor(1, 'green', '√')
}}
if(this.id == 'inp_pwd'){
if(this.value == ''){
changeColor(2, 'red', '密码不能为空')
}else if(this.value.length < 3){
changeColor(2, 'red', '密码长度不够')
}else{
changeColor(2, 'green', '√')
}}
if(this.id == 'inp_re'){
if(this.value == ''){
changeColor(3, 'red', '密码不能为空')
}else if(this.value.length < 3){
changeColor(3, 'red', '密码长度不够')
}else if(this.value != input_element[2].value){
changeColor(3, 'red', '二次密码不一致')
}else{
changeColor(3, 'green', '√')
}}
})
}
</script>
</body>
</html>