什么是正则表达式?它有什么作用?
又称规则表达式,(Regular Expression,在代码中常简写为regex、regexp或RE),是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为”元字符”),是计算机科学的一个概念。
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式(规则)的文本。
如何使用正则表达式
定义表达式
- 普通方式
let reg=/表达式/修饰符(可选)
修饰符
g:代表可以进行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
i:代表不区分大小写匹配。
m:代表可以进行多行匹配。
例如
var reg=/a*b/;
var reg=/abc+f/g;
- 构造函数方式
let reg=new RegExp(“表达式”,”附加参数”);
例如
var reg=new RegExp(“a*b”);
var reg=new RegExp(“abc+f”,”g”);
- 两者区别
1、普通方式中的表达式必须是一个常量字符串,
2、构造函数中的表达式可以是常量字符串,也可以是一个js变量,
3、例如根据用户的输入来作为表达式参数等等:var reg=new RegExp(动态变量,”g”);
表达式操作
1、test(str) 判断字符串str是否匹配表达式,返回一个布尔值。
let regx=/123/;
let flag=regx.test('123sdsd'); // 匹配123sdsd中是否包含123, 结果 flag 返回 true
2、exec(str) 返回str中与表达式相匹配的第一个字符串,而且以数组的形式表现
var str="the name 123 and 456";
var reg=/\d/g; reg.lastIndex=15; // 在全局模式下可以使用lastIndex属性设置在字符串中查找指定字符时开始的位置。
console.log(reg.exec(str)); ['4', index: 17, input: 'the name 123 and 456', groups: undefined]
如果有多个合适的匹配,则第一次执行exec返回一个第一个匹配,此时继续执行exec,则依次返回第二个第三个匹配。 例如:
var regx=/user\d/g;
var rs=regx.exec('ddduser1dsfuser2dd');
var rs1=regx.exec('ddduser1dsfuser2dd');
console.log(rs) ['user1', index: 3, input: 'ddduser1dsfuser2dd', groups: undefined] console.log(rs1)['user2', index: 11, input: 'ddduser1dsfuser2dd', groups: undefined]
// 当然注意regx中的g参数是必须的,否则无论exec执行多少次,都返回第一个匹配。后面还有相关内容涉及到对此想象的解释
3、match(expr) 返回与expr相匹配的一个字符串数组,如果没有加参数g,则返回第一个匹配,加入参数g则返回所有的匹配
var regx=/user\d/g;
var str='user13userddduser345';
var rs=str.match(regx);
console.log(rs) ['user1', 'user3']
4、search(expr),返回字符串中与expr相匹配的第一个匹配的index值。
var regx=/user\d/g;
var str='user13userddduser345';
var rs=str.search(regx);
console.log(rs) 、// 0
5、replace(expr,str),将字符串中匹配expr的部分替换为str。另外在replace方法 中,str中可以含有一种变量符号$,格式为$n,代表匹配中被记住的第n的匹配字符串(注意小括号可以记忆匹配)
示例一:
var regx=/user\d/g;
var str='user13userddduser345';
var rs=str.replace(regx,'00');
console.log(rs) 003userddd0045
示例二:
var regx=/u(se)r\d/g;
var str=“user13userddduser345”;
var rs=str.replace(regx,”$1”);
console.log(rs) // se3userdddse45
对于replace(expr,str)方法还要特别注意一点,如果expr是一个表达式对象则会进行全局替换(此时表达式必须附加参数g,否则也只是替换第一个匹配),如果expr是一个字符串对象,则只会替换第一个匹配的部分,例如:
var regx='user';
var str='user13userddduser345';
var rs=str.replace(regx,'00');
console.log(rs)
6、split(expr),将字符串以匹配expr的部分做分割,返回一个数组,而且表达式是否附加参数g都没有关系,结果是一样的。
var regx=/user\d/g;
var str='user13userddduser345';
var rs=str.split(regx);
console.log(rs) // ['', '3userddd', '45']
正则表达式模式
方括号查询范围内符合的内容
正则表达式模式 | 说明 |
---|---|
[abc] | 查找方括号之间的任何字符。 |
[0-9] | 查找任何从 0 至 9 的数字。 |
(x | y) |
元字符是拥有特殊含义的字符 | |
元字符 | 说明 |
—- | —- |
\d | 查找数字。 |
\D | 查找非数字字符 |
\s | 查找空白字符。 |
\S | 查找非空白字符 |
\b | 匹配单词边界 |
\B | 匹配非单词边界 |
量词: | |
元字符 | 说明 |
—- | —- |
^ | 匹配开头,在多行检测中,会匹配一行的开头 |
$ | 匹配结尾,在多行检测中,会匹配一行的结尾 |
n+ | 匹配任何包含至少一个 n 的字符串。 |
n* | 匹配任何包含零个或多个 n 的字符串。 |
n? | 匹配任何包含零个或一个 n 的字符串。 |
n{x} | 匹配包含 x 个 n 的序列的字符串 |
n{x,y} | 匹配包含最少 x 个、最多 y 个 n 的序列的字符串 |
n{x,} | 匹配包含至少 x 个 n 的序列的字符串 |
示例如下:
var s = "how are you";
var r = /\w+$/;
var a = s.match(r); //返回数组["you"]
var r = /^\w+/;var a = s.match(r); //返回数组["how"]
var r = /\w+/g;var a = s.match(r); //返回数组["how","are","you"]
常用一些表达式
1、手机校验
//手机号校验
const phoneReg = /^[1][3,4,5,6,7,8,9][0-9]{9}$/
//身份证的校验
const sfzReg = /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
//邮箱的校验
const emailReg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/
//URL的校验
const urlReg = /^((https?|ftp|file):\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/
//IPv4的校验
const ipv4Reg = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
//16进制颜色的校验
const color16Reg = /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/
//日期 YYYY-MM-DD
const dateReg = /^\d{4}(\-)\d{1,2}\d{1,2}$/
//日期 YYYY-MM-DD hh:mm:ss
const dateReg = /^(\d{1,4})(-|\/)(\d{1,2})(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/
//整数的校验
const intReg = /^[-+]?\d*$/
//小数的校验
const floatReg = /^[-\+]?\d+(\.\d+)?$/
//保留n位小数
function checkFloat(n) {
return new RegExp(`^([1-9]+[\d]*(.[0-9]{1,${n}})?)$`)
}
// 保留2位小数
const floatReg = checkFloat(2)
const floatNum1 = 1234.5
console.log(floatReg.test(floatNum1)) // true
//邮政编号的校验
const postalNoReg = /^\d{6}$/
//QQ号的校验5-11位数字
const qqReg = /^[1-9][0-9]{4,10}$/
//微信号的校验 说明:6至20位,以字母开头,字母,数字,减号,下划线
const wxReg = /^[a-zA-Z]([-_a-zA-Z0-9]{5,19})+$/
//车牌号的校验
const carNoReg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$/
//只含字母的字符串
const letterReg = /^[a-zA-Z]+$/
//包含中文的字符串
const cnReg = /[\u4E00-\u9FA5]/
//密码强度的校验 说明:密码中必须包含字母、数字、特称字符,至少8个字符,最多30个字符
const passwordReg = /(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[^a-zA-Z0-9]).{8,30}/
//字符串长度n的校验
function checkStrLength(n) {
return new RegExp(`^.{${n}}$`)
}
// 校验长度为3的字符串
const lengthReg = checkStrLength(3)
const str1 = 'hhh'
console.log(lengthReg.test(str1)) // true
//文件拓展名的校验
function checkFileName (arr) {
arr = arr.map(name => `.${name}`).join('|')
return new RegExp(`(${arr})$`)
}
const filenameReg = checkFileName(['jpg', 'png', 'txt'])
//匹配img和src
const imgReg = /<img.*?src=[\"|\']?(.*?)[\"|\']?\s.*?>/ig
const htmlStr = '<div></div><img src="sunshine.png" /><img src="sunshine111.png" />'
console.log(imgReg.exec(htmlStr))
2、邮箱校验
var reg = new RegExp("^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$");
//校验
if (value==null){
alert("邮箱地址不能为空");
return false;
}
if(!reg.test(value)){
alert("请输入有效的邮箱地址");
return false;
}
return true;
3、身份证号校验
const validateIdent = {
aIdentityCode_City: { // 城市代码列表
11: "北京", 12: "天津", 13: "河北", 14: "山西", 15: "内蒙古", 21: "辽宁", 22: "吉林",
23: "黑龙江 ", 31: "上海", 32: "江苏", 33: "浙江", 34: "安徽", 35: "福建", 36: "江西",
37: "山东", 41: "河南", 42: "湖北 ", 43: "湖南", 44: "广东", 45: "广西", 46: "海南",
50: "重庆", 51: "四川", 52: "贵州", 53: "云南", 54: "西藏 ", 61: "陕西", 62: "甘肃",
63: "青海", 64: "宁夏", 65: "新疆", 71: "台湾", 81: "香港", 82: "澳门", 91: "国外 "
},
IdentityCode_isCardNo(card) {//检查号码是否符合规范,包括长度,类型
var reg = /(^\d{15}$)|(^\d{17}(\d|X)$)/; //身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X
if (reg.test(card) === false) {
return false;
}
return true;
},
IdentityCode_checkProvince(card) { //取身份证前两位,校验省份
var province = card.substr(0, 2);
if (validateIdent.aIdentityCode_City[province] == undefined) {
return false;
}
return true;
},
IdentityCode_checkBirthday(card) { //检查生日是否正确,15位以'19'年份来进行补齐。
var len = card.length;
//身份证15位时,次序为省(3位)市(3位)年(2位)月(2位)日(2位)校验位(3位),皆为数字
if (len == '15') {
var re_fifteen = /^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/;
var arr_data = card.match(re_fifteen); // 正则取号码内所含出年月日数据
var year = arr_data[2];
var month = arr_data[3];
var day = arr_data[4];
var birthday = new Date('19' + year + '/' + month + '/' + day);
return validateIdent.IdentityCode_verifyBirthday('19' + year, month, day, birthday);
}
//身份证18位时,次序为省(3位)市(3位)年(4位)月(2位)日(2位)校验位(4位),校验位末尾可能为X
if (len == '18') {
var re_eighteen = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/;
var arr_data = card.match(re_eighteen); // 正则取号码内所含出年月日数据
var year = arr_data[2];
var month = arr_data[3];
var day = arr_data[4];
var birthday = new Date(year + '/' + month + '/' + day);
return validateIdent.IdentityCode_verifyBirthday(year, month, day, birthday);
}
return false;
},
IdentityCode_verifyBirthday(year, month, day, birthday) {//校验日期 ,15位以'19'年份来进行补齐。
var now = new Date();
var now_year = now.getFullYear();
//年月日是否合理
if (birthday.getFullYear() == year
&& (birthday.getMonth() + 1) == month
&& birthday.getDate() == day) {
//判断年份的范围(3岁到150岁之间)
var time = now_year - year;
if (time >= 3 && time <= 150) {
return true;
}
return false;
}
return false;
},
IdentityCode_checkParity(card) { //校验位的检测
card = validateIdent.IdentityCode_changeFivteenToEighteen(card); // 15位转18位
var len = card.length;
if (len == '18') {
var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
var cardTemp = 0, i, valnum;
for (i = 0; i < 17; i++) {
cardTemp += card.substr(i, 1) * arrInt[i];
}
valnum = arrCh[cardTemp % 11];
if (valnum == card.substr(17, 1)) {
return true;
}
return false;
}
return false;
},
IdentityCode_changeFivteenToEighteen(card) { //15位转18位身份证号
if (card.length == '15') {
var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
var cardTemp = 0, i;
card = card.substr(0, 6) + '19' + card.substr(6, card.length - 6);
for (i = 0; i < 17; i++) {
cardTemp += card.substr(i, 1) * arrInt[i];
}
card += arrCh[cardTemp % 11];
return card;
}
return card;
},
IdentityCodeValid(card) {// 身份证号码检验主入口
let pass = true;
let sex = ''
//是否为空
if (pass && card === '')
pass = false;
//校验长度,类型
if (pass && validateIdent.IdentityCode_isCardNo(card) === false)
pass = false;
//检查省份
if (pass && validateIdent.IdentityCode_checkProvince(card) === false)
pass = false;
//校验生日
if (pass && validateIdent.IdentityCode_checkBirthday(card) === false)
pass = false;
//检验位的检测
if (pass && validateIdent.IdentityCode_checkParity(card) === false)
pass = false;
if (pass) {
var iCard = validateIdent.IdentityCode_changeFivteenToEighteen(card);
if (parseInt(iCard.charAt(16)) % 2 == 0) {
sex = "0"; // 女生
} else {
sex = "1"; // 男生
}
return true
} else {
return false
}
}
}
export default validateIdent.IdentityCodeValid //导出