正则表达式以及正则在JS表单校验中的应用
1. 正则表达式的引入
表单验证两种常用的方法:
<input type="submit" onclick="return validate()"/><form action="/aa" onsubmit="return validate()"/>
这里我们使用QQ号码作为表单验证来测试,我们知道QQ号码的规则还是比较复杂,但是这里我们仅仅使用以下三条规则来讲解:
1. qq号必须是5-10位
2. 数字0不可以作为qq号码的开头
3. QQ号码必须是纯数字组成
代码示例如下所示:
<input type="submit" onclick="return validate()"/><form action="/aa" onsubmit="return validate()"/>
当然除了在form表单中添加onsubmit事件来实现表单验证,我们还可以使用在submit类型的input标签中添加onclick事件来实现表单验证,代码如下所示:
<form action="server/server.html" method="get" > QQ账号: <input id="qq" type="text" placeholder="请输入QQ账号..."> <span id="msg"></span> <br> <input type="submit" value="登录" onclick="return checkQQ();"> </form>
相信大家对上述代码都能够理解,但是大家应该也发现了使用传统的if-else来校验qq号码,代码非常冗余,而且可读性很差,何况才短短两条规则就写了这么多的判断,那真实的qq号码肯定规则更多,如果让你去验证邮箱,或者网址呢?所以我们非常有必要学习一门新的技术用于我们JS表单校验,它就是正则表达式了。
2. 正则表达式概述
正则表达式简介
为什么需要正则表达式?
1.本质是用来对复杂文本进行处理。
2.当然也可以用于数据校验
3.文本匹配、搜索、分割、替换等等
正则表达式的优势和用途?
一种强大而灵活的文本处理工具;
提供了一种紧凑的、动态的方式,能够以一种完全通用的方式来解决各种字符串处理(例如:验证、查找、替换等)问题;
大部分语言、数据库都支持正则表达式。
正则表达式定义:
正如他的名字一样是描述了一个规则,通过这个规则可以匹配一类字符串。
正则表达式的用处:
验证给定字符串是否符合指定特征,比如验证是否是合法的邮件地址。
用来查找字符串,从一个长的文本中查找符合指定特征的字符串。
用来替换,比普通的替换更强大,用来替换满足某个规则的字符串
用来分割,比普通的分割更强大,用来分割满足某个规则的字符串
3. 工具软件的使用
3.1. 工具软件RegexBuddy的使用
为了提高开发效率,一般都先在工具软件中测试正则表达式,通过测试后,才在程序中使用。
3.2 正则表达式图形化显示网站 Regexper
由于正则表达式非常灵活,正则表达式本身的可读性非常差,所以比较复杂的正则表达式阅读起来相对比较困难,所以我们可以借助一个图形化正则表达式网站来帮助我们分析一个相对复杂的正则表达式。
正则图形化显示网站://regexper.com//regexr-cn.com
图形化显示结果如下所示:
4. 正则表达式规则
4.1 普通字符
字母、数字、汉字、下划线、以及没有特殊定义的标点符号,都是“普通字符”。表达式中的普通字符,在匹配一个字符串的时候,匹配与之相同的一个字符。例如字符a, b, c ,1,2,中等等。
4.2 转义字符
n 代表换行符 t 制表符 \ 代表本身 ^ ,$,.,(, ) , {, } , ? , + , * , | ,[, ] 匹配这些字符本身 4.3 字符集合
[ ]方括号匹配方式,能够匹配方括号中任意一个字符
[ab5@] 匹配 “a” 或 “b” 或 “5” 或 “@” [^abc] 匹配 “a”,”b”,”c” 之外的任意一个字符 [f-k] 匹配 “f”~”k” 之间的任意一个字母 [^A-F0-3] 匹配 “A”~”F”,”0″~”3″ 之外的任意一个字符 显示效果如下所示:
注意: 正则表达式中的特殊符号,如果被包含于中括号中,则失去特殊意义,但 [ ] : ^ – 除外。
4.4 预定义字符
还有一些字符是正则表达式语法事先定义好的,有特殊的含义,能够与 ‘多种字符’ 匹配的表达式
d 任意一个数字,0~9 中的任意一个 w 任意一个字母或数字或下划线,也就是 A~Z,a~z,0~9,_ 中任意一个 s 包括空格、制表符、换行符等空白字符的其中任意一个 . 小数点可以匹配除了换行符(n)以外的任意一个字符 注意: 如果是D,W,S表示相反的意思。
4.5 量词
{n} 表达式重复n次 {m,n} 表达式至少重复m次,最多重复n次 {m,} 表达式至少重复m次 ? 匹配表达式0次或者1次,相当于 {0,1} + 表达式至少出现1次,相当于 {1,} * 表达式不出现或出现任意次,相当于 {0,} 显示效果如下所示:
表达式至少重复2次,最多重复4次
至少3次:
匹配表达式0次或者1次,相当于 {0,1}.
+至少一次
表达式不出现或出现任意次,相当于 {0,}
4.6 贪婪模式和非贪婪模式
匹配次数中的贪婪模式(匹配字符越多越好)
“{m,n}”, “{m,}”, “?”, “*”, “+”,具体匹配的次数随被匹配的字符串而定。这种重复匹配不定次数的表达式在匹配过程中,总是尽可能多的匹配。
匹配次数中的非贪婪模式(匹配字符越少越好)
在修饰匹配次数的特殊符号后再加上一个 “?” 号,则可以使匹配次数不定的表达式尽可能少的匹配,使可匹配可不匹配的表达式,尽可能地 “不匹配”。
4.7 边界字符
(本组标记匹配的不是字符而是位置,符合某种条件的位置)
^ 与字符串开始的地方匹配 $ 与字符串结束的地方匹配 b 匹配一个单词边界 显示效果如下所示:
4.8 选择符和分组
表达式 作用 | 左右两边表达式之间 “或” 关系,匹配左边或者右边 ( ) (1). 在被修饰匹配次数的时候,括号中的表达式可以作为整体被修饰(2). 取匹配结果的时候,括号中的表达式匹配到的内容可以被单独得到(3). 每一对括号会分配一个编号,使用 () 的捕获根据左括号的顺序从 1 开始自动编号。捕获元素编号为零的第一个捕获是由整个正则表达式模式匹配的文本 选择符操作显示效果如下所示:
分组:
4.9 反向引用(nnn)
1. 每一对()会分配一个编号,使用 () 的捕获根据左括号的顺序从 1 开始自动编号。
2. 通过反向引用,可以对分组已捕获的字符串进行引用。
5. 正则表达式的匹配模式
5.1 IGNORECASE 忽略大小写模式
1. 匹配时忽略大小写。
2. 默认情况下,正则表达式是要区分大小写的。
5.2 SINGLELINE 单行模式
1. 整个文本看作一个字符串,只有一个开头,一个结尾。
2.使小数点 “.” 可以匹配包含换行符(n)在内的任意字符。
5.3 MULTILINE 多行模式
1.每行都是一个字符串,都有开头和结尾。
2.在指定了 MULTILINE 之后,如果需要仅匹配字符串开始和结束位置,可以使用 A 和 Z
6.开发中使用正则表达式的流程
1. 分析所要匹配的数据,写出测试用的典型数据
2. 在工具软件中进行匹配测试
3. 在程序中调用通过测试的正则表达式
7. 课堂练习
电话号码验证
(1)电话号码由数字和”-“构成
(2)电话号码为7到8位(不加区号)
(3)如果电话号码中包含有区号,那么区号为三位或四位, 首位是0.
(4)区号用”-“和其他部分隔开
(5)移动电话号码为11位
(6)11位移动电话号码的第一位和第二位为”13“,”15”,”18”
0(d{2,3})-d{7,8}
(13)|(15)|(18)d{9}
8. Java中使用正则表达式
相关类位于:java.util.regex包下面
类 Pattern:
正则表达式的编译表示形式。
Pattern p = Pattern.compile(r); //建立正则表达式,并启用相应模式
类 Matcher:
通过解释 Pattern 对 character sequence 执行匹配操作的引擎
Matcher m = p.matcher(str); //匹配str字符串
编程中使用正则表达式常见情况:
验证表达式是否匹配整个字符串
验证表达式是否可以匹配字符串的子字符串
返回给定字符串中匹配给定正则表达式所有子字符串
替换给定字符串中匹配正则表达式的子字符串
根据正则表达式定义规则截取字符串
9. JAVASCRIPT中使用正则表达式
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <!-- QQ账号的验证: 1.qq号必须是5-10位 2.数字0不可以作为qq号码的开头 --> <form action="server/server.html" method="get" onsubmit="return checkQQ()"> QQ账号: <input id="qq" type="text" placeholder="请输入QQ账号..."> <span id="msg"></span> <br> <input type="submit" value="登录"> </form> <script> function checkQQ() { var qq = document.getElementById("qq").value; var msg = document.getElementById("msg"); // 默认qq号码是合格的 var flag = true; // 保证5-10位 if(qq.length >= 5 && qq.length <= 10) { // 保证不是0开头 if(qq.charAt(0) != 0) { // 保证是数字 for(var i = 0; i < qq.length; i++) { var ch = qq.substr(i,1); if(!(ch >= '0' && ch <= '9')) { flag = false; msg.innerText = "XXX QQ号码必须是数字!!!" msg.style.color = "red"; break; } } } else { flag = false; msg.innerText = "XXX QQ号码不能以数字0开头!!!" msg.style.color = "red"; } } else { flag = false; msg.innerText = "XXX QQ号码的位数必须在5~10之间!!!" msg.style.color = "red"; } return flag; } </script></body></html>
Flags可选项常见值:
g (全文查找出现的所有pattern)(没有g只会匹配一次)
i (忽略大小写)
<form action="server/server.html" method="get" > QQ账号: <input id="qq" type="text" placeholder="请输入QQ账号..."> <span id="msg"></span> <br> <input type="submit" value="登录" onclick="return checkQQ();"> </form>
RegExp对象常用方法:
exec(): 返回的是一个数组。该数组包含了匹配该模式的第一个子字符串以及该子字符串中匹配相关分组的字符串。比如:
var re = new RegExp("(\d+)([a-z]+)","ig");var result = re.exec("33ff55tt77uu88yy");
返回的数组为:[33ff,33,ff]
test(): 返回一个 Boolean 值,它指出在被查找的字符串中是否存在模式匹配的子字符串
//test 查找是否 存在的字符串var str1 = "abc123abc123";//判断字符串是否都是数字var reg3 = /^d+$/;var flag = reg3.test(str1);console.log(flag);
字符串中常用的使用正则表达式的方式:
match():使用正则表达式模式对字符串执行查找,并将符合该模式的所有子字符串包含到数组中返回。
var re = new RegExp("(\d+)([a-z]+)","ig");var reg = /(d+)([a-z]+)/gi;var t = "33ff55tt77uu88yy".match(re);
结果为数组:[33ff,55tt,77uu,88yy]
search(): 返回与正则表达式查找内容匹配的第一个子字符串的位置
var reg = /d+/g; // 数组正则var index = "33ff55tt77uu88yy".search(reg);split(regex):按照指定的模式切割字符串,返回一个数组。var t = "asdfd33ff55tt77uu88yy".split(/d+/);replace(): 替换var t = "asdfd3355tt77uu88yy".replace(/d+/g,"#");代码示例如下所示:// 替换// 指定为global模式,否则只替换第一个子字符串var reg4= /d+/g;var str2 = str1.replace(reg4,"#");console.log(str2);
10. 针对表单域的验证,封装一个通用的函数
我们可以编写一个简单的用户名验证的方法,代码如下所示:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Js表单正则验证</title></head><body> <form action="server/server.html" method="get">用户名:<input type="text" id="nameId" name="name" onblur="checkName();"><span id="msg"></span><br>密码: <input type="password" name="pwd"><br> <input type="submit"> </form> <script> /* 表单验证: 实现思路: 1.给input标签添加onblur事件 2.获取input标签输入的内容 3.判断是否输入合法 4.dom操作修改页面提示信息 */ function checkName() { var nameInputValue = document.getElementById("nameId").value; var msg = document.getElementById("msg"); var reg = /^[u4e00-u9fa5]{2,10}$/; if(reg.test(nameInputValue)) { msg.innerText = "√ 用户名合法!!!" msg.style.color = "red"; } else { msg.innerText = "X 用户名必须是2-10个中文字符!!!" msg.style.color = "red"; } } </script></body></html>
这里我们通过输入框失去焦点来对输入的内容进行验证,验证的步骤也非常简单,步骤基本如下所示:
1. 给表单域添加onblur失去焦点事件
2. 获取表单域输入框的内容
3. 通过正则表达式判断输入是否合法
4. 根据是否合法显示不同的页面提示信息
通过观察我们不难发现,不仅验证用户名,验证邮箱,密码,身份证等等基本上步骤都是一样的,但是有一些例如正则表达式或者显示的正确或者错误信息是变化的,所以我们可以对验证的方法进行封装,将变化的抽取成为形参,从而用于其他的表单校验,代码如下所示:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <!-- 表单验证: 1. 如果三个验证有一个失败 不能提交数据 2. 验证的时候需要有错误信息提示 思路: 1. 添加onsubmit 方法(在表单提交数据前执行的 事件) 2. 验证的时候 用户密码邮箱等存在重复的代码 可以进行封装 --> <form method="get" action="/demo01" onsubmit="return checkForm()"> 用户名:<input id="nameId" type="text" name="name"/><span id="msgName"></span><br> 密码:<input id="pwdId" type="password" name="name"/><span id="msgPwd"></span><br> 邮箱:<input id="emailId" type="text" name="email"><span id="msgEmail"></span><br> <input type="submit"/> </form> <script> function checkForm() { // 验证用户名 // 2~10个汉字var regex1 = /^[u4e00-u9fa5]{2,10}$/; var nameFlag = checkInput("nameId","msgName",regex1,"√ 输入合格","x 必须是2~10个汉字!!!"); // 验证密码 // 6个数字的密码 var regex2 = /^d{6}$/; var pwdFlag = checkInput("pwdId", "msgPwd", regex2, "√ 输入合格", "x 必须是6个存数字组成!!!"); // 验证邮箱 var regex3 = /^w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*$/; var emailFlag = checkInput("emailId", "msgEmail", regex3, "√ 输入合格", "x 邮箱格式不正确!!!"); console.log(nameFlag); console.log(pwdFlag); console.log(emailFlag); return nameFlag && pwdFlag && emailFlag;} function checkInput(objId, msgId, regex, successMsg, errMsg) { var inputNodeValue = document.getElementById(objId).value; var spanNode = document.getElementById(msgId); if(regex.test(inputNodeValue)) { spanNode.innerText = successMsg; spanNode.style.color = "green"; return true; } else { spanNode.innerText = errMsg; spanNode.style.color = "red"; return false; } } </script></body></html>