正则表达式
正则表达式简介
什么是正则表达式
正则表达式:用于匹配规律规则的表达式,正则表达式最初是科学家对人类神经系统的工作原理的早期研究,现在在编程语言中有广泛的应用。正则表通常被用来检索、替换那些符合某个模式(规则)的文本。
正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符")。
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。
正则表达式是繁琐的,但它是强大的,学会之后的应用会让你除了提高效率外,会给你带来绝对的成就感。
许多程序设计语言都支持利用正则表达式进行字符串操作。
正则表达式的作用
通过使用正则表达式,可以:
-
测试字符串内的模式(匹配)。 例如,可以测试输入字符串,以查看字符串内是否出现电话号码模式或信用卡号码模式。这称为数据验证。
-
替换文本(替换)。 可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它。
-
基于模式匹配从字符串中提取子字符串(提取)。 可以查找文档内或输入域内特定的文本
正则表达式的特点
灵活性、逻辑性和功能性非常的强
可以迅速地用极简单的方式达到字符串的复杂控制
对于刚接触的人来说,比较晦涩难懂
发展历史
正则表达式的"祖先"可以一直上溯至对人类神经系统如何工作的早期研究。Warren McCulloch 和 Walter Pitts 这两位神经生理学家研究出一种数学方式来描述这些神经网络。
1956 年, 一位叫 Stephen Kleene 的数学家在 McCulloch 和 Pitts 早期工作的基础上,发表了一篇标题为"神经网事件的表示法"的论文,引入了正则表达式的概念。正则表达式就是用来描述他称为"正则集的代数"的表达式,因此采用"正则表达式"这个术语。
随后,发现可以将这一工作应用于使用 Ken Thompson 的计算搜索算法的一些早期研究,Ken Thompson 是 Unix 的主要发明人。正则表达式的第一个实用应用程序就是 Unix 中的 qed 编辑器。
如他们所说,剩下的就是众所周知的历史了。从那时起直至现在正则表达式都是基于文本的编辑器和搜索工具中的一个重要部分。
应用领域
目前,正则表达式已经在很多软件中得到广泛的应用,包括 *nix(Linux, Unix等)、HP 等操作系统,PHP、C#、Java 等开发环境,以及很多的应用软件中,都可以看到正则表达式的影子。
正则表达式的组成
-
普通字符abc 123
-
特殊字符(元字符):正则表达式中有特殊意义的字符\d \w
字符类:
字符类 | 说明 |
---|---|
[abc] | 只能是a b c中的任意一个,也就是说[]里面的内容只能选择任意一个 |
[^abc] | 任何字符,除了 a、b 或 c(否定) |
[a-z] | a 到 z 中的任意一个 |
[^a-z] | 非a 到 z 中的任意一个 |
[a-zA-Z] | a 到 z 或 A 到 Z,两头的字母包括在内(范围) |
[0-9] | 0-9之间的任意一个 |
[\u4e00-\u9fa5] | 表示汉字的取值范围 |
元字符:
元字符 | 说明 |
---|---|
\d | 匹配数字 |
\D | 匹配任意非数字的字符 |
\w | 匹配字母或数字或下划线 |
\W | 匹配任意不是字母,数字,下划线 |
\s | 匹配任意的空白符 |
\S | 匹配任意不是空白符的字符 |
. | 匹配除换行符以外的任意单个字符 |
^ | 表示匹配行首的文本(以谁开始) |
$ | 表示匹配行尾的文本(以谁结束) |
限定符:
限定符 | 说明 |
---|---|
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
条件:
条件 | 说明 |
---|---|
(?![0-9]+$) | 不能全是数字 |
(?![a-zA-Z]+$) | 不能全是字母 |
其他
其他 | 说明 |
---|---|
[] | 字符串用中括号括起来,表示匹配其中的任一字符 |
[^] | 匹配除中括号以内的内容 |
\ | 转义符 |
| | 或者,选择两者中的一个。注意 | 将左右两边分为两部分,而不管左右两边有多长多乱 |
() | 从两个直接量中选择一个,分组 |
简单案例
验证手机号:^\d{11}$
验证邮编:^\d{6}$
验证日期 2012-5-01:^\d{4}-\d{1,2}-\d{1,2}$
验证邮箱 xxx@newcapec.com.cn:^\w+@\w+\.\w+$
验证IP地址 192.168.1.10:^\d{1,3}(.\d{1,3}){3}$
使用正则表达式
创建正则对象
方式1:
var reg = new RegExp('\d', 'i');
var reg = new RegExp('\d', 'gi');
方式2:
var reg = /\d/i;
var reg = /\d/gi;
参数
标志 | 说明 |
---|---|
i | 忽略大小写 |
g | 全局匹配 |
gi | 全局匹配+忽略大小写 |
正则匹配
/*
正则的作用: 匹配、替换、提取
1、作为正则对象来用,用来调用匹配方法 (匹配)
正则对象.test(字符串)
var reg = /^正则规则$/
new RegExp(pattern, attributes);
pattern:一个字符串,指定了正则表达式的模式或其他正则表达式。
attributes:一个可选的字符串,包含属性“g”、“i”和“m”,分别用于指定全局匹配、区分大小写的匹配和多行匹配
regexp.test(string)
string:要检测的字符串。
如果字符串string中含有与regexp匹配的文本,就返回true,否则返回false。
2、作为正则参数来用,用来作为方法的参数 (替换、提取)
字符串.replace(正则,字符串)
字符串.replace(/正则规则/,字符串)
*/
// 电话号码
var tel_reg = /^\d{11}$/;
var tel = "12311111111";
console.log("电话号码是否符合规则:" + tel_reg.test(tel));
// 邮编
var postcode_reg = /^\d{6}$/;
// 验证日期 2012-5-01
var date_reg = /^\d{4}(-\d{1,2}){1,2}$/;
// var date_reg = /^\d{4}-\d{1,2}-\d{1,2}$/;
var date1 = "2020-05";
var date2 = "2020-09-1";
var date3 = "2020";
console.log("日期是否符合规则:" + date_reg.test(date1));
console.log("日期是否符合规则:" + date_reg.test(date2));
console.log("日期是否符合规则:" + date_reg.test(date3));
// 邮箱 .com.cn
var email_reg = /^[A-Za-z0-9]{5,}@[a-z0-9]{2,5}(\.[a-z]{2,3}){1,2}$/;
// var email_reg = /^\w+@\w+\.\w+$/;
var email1 = "2@q.com";
var email2 = "zhangsan@163.com";
var email3 = "32132@qq.com";
var email4 = "zhangsan123@yahoo.com.cn";
console.log("邮箱是否符合规则:" + email_reg.test(email1));
console.log("邮箱是否符合规则:" + email_reg.test(email2));
console.log("邮箱是否符合规则:" + email_reg.test(email3));
console.log("邮箱是否符合规则:" + email_reg.test(email4));
// ip校验
var ip_reg = /^\d{1,3}(.\d{1,3}){3}$/;
// 用户名,8-20为字母、数子、下划线,不能全是数字
var userName_reg = /^(?![0-9]+$)\w{8,20}$/;
var userName = "12345678";
console.log("用户名是否符合规则:" + userName_reg.test(userName))
正则提取
<!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>
<script>
// 1. 提取工资
var str = "张三:1000,李四:5000,王五:8000。";
var array = str.match(/\d+/g);
console.log(array);
// 2. 提取email地址
var str =
"123123@xx.com,fangfang@valuedopinions.cn 286669312@qq.com 2、emailenglish@emailenglish.englishtown.com 286669312@qq.com...";
var array = str.match(/\w+@\w+\.\w+(\.\w+)?/g);
console.log(array);
// 3. 分组提取
// 3. 提取日期中的年部分 2015-5-10
var dateStr = '2016-1-5';
// 正则表达式中的()作为分组来使用,获取分组匹配到的结果用Regex.$1 $2 $3....来获取
var reg = /^(\d{4})-\d{1,2}-\d{1,2}$/;
if (reg.test(dateStr)) {
console.log(RegExp.$1);
}
// 4. 提取邮件中的每一部分
var reg = /^(\w+)@(\w+)\.(\w+)(\.\w+)?$/;
var str = "123123@xx.com";
if (reg.test(str)) {
console.log(RegExp.$1);
console.log(RegExp.$2);
console.log(RegExp.$3);
}
</script>
</body>
</html>
正则替换
// 1. 替换所有空白
var str = " 123AD asadf asadfasf adf ";
str = str.replace(/\s/g,"xx");
console.log(str);
// 2. 替换所有,|,
var str = "abc,efg,123,abc,123,a";
str = str.replace(/,|,/g, ".");
console.log(str);
案例表单验证
常规方式
QQ号:<input type="text" id="txtQQ"><span></span><br>
邮箱:<input type="text" id="txtEMail"><span></span><br>
手机:<input type="text" id="txtPhone"><span></span><br>
生日:<input type="text" id="txtBirthday"><span></span><br>
姓名:<input type="text" id="txtName"><span></span><br>
//获取文本框
var txtQQ = document.getElementById("txtQQ");
var txtEMail = document.getElementById("txtEMail");
var txtPhone = document.getElementById("txtPhone");
var txtBirthday = document.getElementById("txtBirthday");
var txtName = document.getElementById("txtName");
//
txtQQ.onblur = function () {
//获取当前文本框对应的span
var span = this.nextElementSibling;
var reg = /^\d{5,12}$/;
//判断验证是否成功
if(!reg.test(this.value) ){
//验证不成功
span.innerText = "请输入正确的QQ号";
span.style.color = "red";
}else{
//验证成功
span.innerText = "";
span.style.color = "";
}
};
//txtEMail
txtEMail.onblur = function () {
//获取当前文本框对应的span
var span = this.nextElementSibling;
var reg = /^\w+@\w+\.\w+(\.\w+)?$/;
//判断验证是否成功
if(!reg.test(this.value) ){
//验证不成功
span.innerText = "请输入正确的EMail地址";
span.style.color = "red";
}else{
//验证成功
span.innerText = "";
span.style.color = "";
}
};
封装成函数
//获取文本框
var txtQQ = document.getElementById("txtQQ");
var txtEMail = document.getElementById("txtEMail");
var txtPhone = document.getElementById("txtPhone");
var txtBirthday = document.getElementById("txtBirthday");
var txtName = document.getElementById("txtName");
var qq_flag = false;
var email_flag = false;
// 封装共有函数
function check(element, reg, tips) {
element.onfocus = function () {
var nextSpan = this.nextElementSibling;
nextSpan.innerHTML = "请输入您的" + tips;
nextSpan.className = "";
}
element.onblur = function () {
var val = this.value;
var nextSpan = this.nextElementSibling;
if (val.replace(/\s/g, "") === "") {
nextSpan.innerHTML = tips + "不能为空";
nextSpan.className = "error";
} else {
var reg_obj = reg;
if (reg_obj.test(val)) {
nextSpan.innerHTML = "格式正确";
nextSpan.className = "correct";
element.correct = true;
} else {
nextSpan.innerHTML = tips + "格式错误";
nextSpan.className = "error";
}
}
}
}
// 验证qq
var QQ_REG = /^\d{5,}$/;
check(txtQQ, QQ_REG, "QQ号码")
// 验证email
var email_reg = /^[A-Za-z0-9]{5,}@[a-z0-9]{2,5}(\.[a-z]{2,3}){1,2}$/;
check(txtEMail, email_reg, "邮箱地址")
// 验证手机号
var tel_reg = /^\d{11}$/;
check(txtPhone, tel_reg, "手机号码")
var f1 = document.getElementById("f1");
f1.onsubmit = function () {
console.log(txtQQ.correct);
if (!(txtQQ.correct && txtEMail.correct && txtPhone.correct)) {
return false;
}
}
添加自定义验证属性对表单进行验证
<form id="frm">
QQ号:<input type="text" name="txtQQ" data-rule="qq"><span></span><br>
邮箱:<input type="text" name="txtEMail" data-rule="email"><span></span><br>
手机:<input type="text" name="txtPhone" data-rule="phone"><span></span><br>
生日:<input type="text" name="txtBirthday" data-rule="date"><span></span><br>
姓名:<input type="text" name="txtName" data-rule="cn"><span></span><br>
</form>
// 所有的验证规则
var rules = [
{
name: 'qq',
reg: /^\d{5,12}$/,
tip: "请输入正确的QQ"
},
{
name: 'email',
reg: /^\w+@\w+\.\w+(\.\w+)?$/,
tip: "请输入正确的邮箱地址"
},
{
name: 'phone',
reg: /^\d{11}$/,
tip: "请输入正确的手机号码"
},
{
name: 'date',
reg: /^\d{4}-\d{1,2}-\d{1,2}$/,
tip: "请输入正确的出生日期"
},
{
name: 'cn',
reg: /^[\u4e00-\u9fa5]{2,4}$/,
tip: "请输入正确的姓名"
}];
addCheck('frm');
//给文本框添加验证
function addCheck(formId) {
var i = 0,
len = 0,
frm =document.getElementById(formId);
len = frm.children.length;
for (; i < len; i++) {
var element = frm.children[i];
// 表单元素中有name属性的元素添加验证
if (element.name) {
element.onblur = function () {
// 使用dataset获取data-自定义属性的值
var ruleName = this.dataset.rule;
var rule =getRuleByRuleName(rules, ruleName);
var span = this.nextElementSibling;
//判断验证是否成功
if(!rule.reg.test(this.value) ){
//验证不成功
span.innerText = rule.tip;
span.style.color = "red";
}else{
//验证成功
span.innerText = "";
span.style.color = "";
}
}
}
}
}
// 根据规则的名称获取规则对象
function getRuleByRuleName(rules, ruleName) {
var i = 0,
len = rules.length;
var rule = null;
for (; i < len; i++) {
if (rules[i].name == ruleName) {
rule = rules[i];
break;
}
}
return rule;
}
常用正则汇总
校验数字的表达式
数字:^[0-9]*$
n位的数字:^\d{n}$
至少n位的数字:^\d{n,}$
m-n位的数字:^\d{m,n}$
零和非零开头的数字:^(0|[1-9][0-9]*)$
非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(\.[0-9]{1,2})?$
带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})$
正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$
有两位小数的正实数:^[0-9]+(\.[0-9]{2})?$
有1~3位小数的正实数:^[0-9]+(\.[0-9]{1,3})?$
非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
非零的负整数:^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$
非负整数:^\d+$ 或 ^[1-9]\d*|0$
非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
非负浮点数:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
非正浮点数:^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
正浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
负浮点数:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
浮点数:^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$
校验字符的表达式
汉字:^[\u4e00-\u9fa5]{0,}$
英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
长度为3-20的所有字符:^.{3,20}$
由26个英文字母组成的字符串:^[A-Za-z]+$
由26个大写英文字母组成的字符串:^[A-Z]+$
由26个小写英文字母组成的字符串:^[a-z]+$
由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$
中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
可以输入含有^%&',;=?$\"等字符:[^%&',;=?$\x22]+
禁止输入含有~的字符:[^~\x22]+
特殊需求表达式
Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?
InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|4|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$
国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
电话号码正则表达式(支持手机号码,3-4位区号,7-8位直播号码,1-4位分机号): ((\d{11})|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$)
身份证号(15位、18位数字),最后一位是校验位,可能为数字或字符X:(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)
帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在 8-10 之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9]{8,10}$
强密码(必须包含大小写字母和数字的组合,可以使用特殊字符,长度在8-10之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
日期格式:^\d{4}-\d{1,2}-\d{1,2}
一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$
一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$
钱的输入格式:
有四种钱的表示形式我们可以接受:"10000.00" 和 "10,000.00", 和没有 "分" 的 "10000" 和 "10,000":^[1-9][0-9]*$
这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$
一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$
这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧。下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$
必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10" 和 "10.2" 是通过的:^[0-9]+(.[0-9]{2})?$
这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$
这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$
1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$
备注:这就是最终结果了,别忘了"+"可以用"*"替代如果你觉得空字符串也可以接受的话(奇怪,为什么?)最后,别忘了在用函数时去掉去掉那个反斜杠,一般的错误都在这里
xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
中文字符的正则表达式:[\u4e00-\u9fa5]
双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1))
空白行的正则表达式:\n\s*\r (可以用来删除空白行)
HTML标记的正则表达式:<(\S*?)[^>]*>.*?|<.*? /> ( 首尾空白字符的正则表达式:^\s*|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)
腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始)
中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字)
IP地址:((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))