前言
- 细阅此文章大概需要 30分钟左右
- 本篇中详细讲述了:
- 正则表达式是什么
- 正则表达式的处理【匹配】【捕获】
- 创建正则
- 元字符
- 修饰符
- 小括号的作用
- 中括号的作用
- 问号的作用
- 正则匹配[test]
- 正则捕获的多种思路
- 练习题:单词首字母大写
- 练习题:日期字符串格式化
- 处理并封装一个格式化时间字符串的万能方法
- 获取URL地址中的问号传参信息&HASH信息
- 如果有任何问题都可以留言给我,我看到了就会回复,如果我解决不了也可以一起探讨、学习。如果认为有任何错误都还请您不吝赐教,帮我指正,在下万分感谢。希望今后能和大家共同学习、进步。
- 下一篇会尽快更新,已经写好的文章也会在今后随着理解加深或者加入一些图解而断断续续的进行修改。
- 如果觉得这篇文章对您有帮助,还请点个赞支持一下,谢谢大家!
正则表达式
- 正则表达式就是一个用来处理字符串的规则
- 正则表达式就是 由
元字符、修饰符组成 的规则
正则表达式的处理
- 只能处理字符串
- 【匹配】 验证字符串是否符合这个规则
- 【捕获】 把字符串中符合规则的信息获取的
创建正则
字面量方式 let reg1 = /\d+/img;
- 字面量方式,两个斜杠包起来的,都是它的元字符
- 最后一个斜杠后面放的是修饰符,
构造函数方式 let reg2 = new Regexp('\\d+');
- 构造函数方式,传递两个字符串,
- 第一个字符串中放的是元字符
- 当中是两个斜杠的原因,是因为传递的是俩个字符串,字符串中一个右斜杠没有任何意义,所以每次使用需要写两个,其中一个右斜杠是为了转义 【保证语法准确性】
- 第二个字符串中放的是修饰符
元字符
量词元字符 【让左侧的某元字符出现多少次】
* 零到多次
+ 一到多次
? 零次或者一次
{n} 出现n次
{n,} 出现n到多次
{n,m} 出现n到m次
特殊元字符 【有特殊意义的元字符】
\ 转义字符(普通->特殊->普通)
. 除\n(换行符)以外的任意字符
^ 以哪一个元字符作为开始
$ 以哪一个元字符作为结束
\n 换行符
\d 0~9之间的一个数字
\D 非【0~9之间的数字】的字符 (大写和小写的意思是相反的)
\w 数字、字母、下划线中的任意一个字符
\s 一个空白字符(包含空格、制表符、换页符等)
\t 一个制表符(一个TAB键:四个空格)
\b 匹配一个单词的边界
x|y x或者y中的一个字符 【使用时一般的伴随着小括号分组,可以改变默认的优先级】
[xyz] x或者y或者z中的一个字符
- 中括号具有消磁的作用,在中括号中出现的元字符都是本身的含义
- 但是像是
\d之类的元字符,算是一个元字符,本身的意思就是0-9之间的一个数字
- 中括号中出现的多位数代表着啥或啥,并不是多位数
[^xy] 除了x/y以外的任意字符
[a-z] 指定a-z这个范围中的任意字符 如 [0-9a-zA-Z_]===\w [0-9] === \d
[^a-z] 上一个的取反“非”
() 正则中的分组符号
(?:) 只匹配不捕获
(?=) 正向预查
(?!) 负向预查
普通元字符
修饰符
i =>ignoreCase 忽略单词大小写匹配
m =>multiline 可以进行多行匹配
g =>global 全局匹配
小括号的作用
- 【优先级】 :可以改变默认的优先级
- 【分组捕获】 :第一次捕获的时候,除了把大正则匹配的信息捕获到,而且还可以单独把每一个小分组匹配的信息捕获到
中括号的作用
- 【分组引用】:
\1或者\2.... 代表 复刻 出和第一个/第二个...分组一模一样的内容
let reg = /^[a-zA-Z\d][a-zA-Z\d]\2\1$/;
问号在正则中的多种作用
- 当?左边是非量词元字符 :它本身就是量词元字符,让左侧内容出现0~1次
/\w?/
- 当?左边是量词元字符 :他的目的是取消捕获时的贪婪性
/\d?/g
- (?:):当前分组只匹配不捕获
- (?=):正向预查(断言),只有符合条件才可以
- (?!):负向预查(断言),只有不符合条件才可以
let reg = /^[a-zA-Z\d]{6,16}$/;
let reg = /^(?!\d+$)(?![a-z]+$)(?![A-Z]+$)(?![a-z\d]+$)(?![A-Z\d]+$)(?![a-zA-Z]+$)[a-zA-Z\d]{6,16}$/;
let reg = /^(?=[a-zA-Z]*\d+[a-zA-Z]*)(?=[A-Z\d]*[a-z]*[A-Z\d]*)(?=[])/
正则匹配:正则对象.test(字符串)
let reg = /\d+/;
console.log(reg.test('hahahahaha'))
console.log(reg.test('hahahahaha2021'))
reg = /^\d+/;
console.log(reg.test('hahahahaha'))
console.log(reg.test('hahahahaha2021'))
console.log(reg.test('2021hahahahaha'))
reg = /\d+$/;
console.log(reg.test('hahahahaha'))
console.log(reg.test('hahahahaha2021'))
console.log(reg.test('2021hahahahaha'))
reg = /^\d+$/;
console.log(reg.test('hahahahaha'))
console.log(reg.test('hahahahaha2021'))
console.log(reg.test('2021hahahahaha'))
console.log(reg.test('2020hahahahaha2021'))
console.log(reg.test('20202021'))
reg = /^\d$/;
console.log(reg.test('1'))
reg = /^2.6$/;
console.log(reg.test('2.6'));
console.log(reg.test('2+6'));
console.log(reg.test('286'));
console.log(reg.test('26'));
console.log(reg.test(`2
6`));
reg = /^2\.6$/;
console.log(reg.test('2.6'));
console.log(reg.test('2+6'));
reg = /^\\d$/;
console.log(reg.test('d'))
console.log(reg.test('\d'))
console.log(reg.test('\\d'))
let reg1 = /^2|6$/;
console.log(reg1.test('2'));
console.log(reg1.test('3'));
console.log(reg1.test('23'));
console.log(reg1.test('4'));
let reg2 = /^(2|6)$/;
console.log(reg2.test('2'));
console.log(reg2.test('3'));
console.log(reg2.test('23'));
console.log(reg2.test('4'));
let reg3 = /^14|56$/;
console.log(reg3.test('14'));
console.log(reg3.test('56'));
console.log(reg3.test('146'));
console.log(reg3.test('145'));
console.log(reg3.test('156'));
console.log(reg3.test('1456'));
console.log(reg3.test('16'));
let reg4 = /^(14|56)$/;
console.log(reg4.test('14'));
console.log(reg4.test('56'));
console.log(reg4.test('146'));
console.log(reg4.test('145'));
console.log(reg4.test('156'));
console.log(reg4.test('1456'));
console.log(reg4.test('16'));
let reg5 = /^[.+]$/
console.log(reg5.test('a'));
console.log(reg5.test('aaaa'));
console.log(reg5.test('.'));
console.log(reg5.test('+'));
let reg6 = /^[\d]$/;
console.log(reg6.test('9'));
console.log(reg6.test('d'));
let reg7 = /^[12-369]$/;
console.log(reg7.test('12'));
console.log(reg7.test('369'));
console.log(reg7.test('19'));
console.log(reg7.test('25'));
console.log(reg7.test('40'));
console.log(reg7.test('1'));
console.log(reg7.test('2'));
console.log(reg7.test('3'));
console.log(reg7.test('6'));
console.log(reg7.test('9'));
console.log(reg7.test('4'));
let ageReg = /^((1[8-9])|([2-5]\d)|(6[0-5]))$/
let phoneReg = /^1\d{10}$/
let passReg = /^[0-9a-zA-Z]{6,16}$/;
`[\u4E00-\u9FA5]`
let chineseNameReg = /^[\u4E00-\u9FA5]{2,10}(·[\u4E00-\u9FA5]{1,10})?$/;
`[\u4E00-\u9FA5]`
let emailReg = /^[\u4E00-\u9FA5]{2,10}(·[\u4E00-\u9FA5]{1,10})?$/;
let emailReg2 = /^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;
正则捕获:正则对象.exec(字符串)
- 把字符串中符合正则匹配规则的内容捕获到
- 若字符串中没有任何信息与正则相匹配,那么获取的结果就是null
正则捕获的特点
- 【'懒'】 ,执行一次或者多次捕获,只能把第一个匹配的信息捕获到 ,后面其他匹配的信息无法捕获到
- 正则的原型对象上有一个 公共属性
lastIndex,存着下次开始查找的索引,默认情况下不会修改其值,为0。 所以每一次捕获都是从第一个字符开始查找的,所以永远只能捕获第一个匹配的
- 正则表达式中有一个修饰符g可设置两个值(global:false/true),默认为false ,这个修饰符是全局匹配 【每一次捕获完,会修改lastIndex值】
- 【重要】 但如果使用加了修饰符g的正则规则,无论是test还是exec,都会修改lastIndex,所以如果连着使用,就会出现问题!!!!!
let str = 'lsw123lsw'
reg = /\d+/,
reg1= /\d+/g;
if(reg.test(str)){
console.log(reg.exec(str));
}
if(reg1.test(str)){
console.log(reg.exec(str));
}
- 【正则捕获还具备贪婪性】
let str = 'lsw2021',
reg = /\d+/g,
reg2 = /\d+?/g;
console.log(str.match(reg));
console.log(str.match(reg2));
解决正则捕获懒的特点
【方法一】 修饰符g可以解决正则捕获懒的特点
let str = 'lsw',
str1 = 'lsw2020happy2021everyday'
reg = /\d+/,
reg1 = /\d+/g;
console.log(reg.test(str));
console.log(reg.exec(str));
reg.test(str)?console.log(reg.exec(str)):null;
console.log(reg.exec(str1));
console.log(reg1.lastIndex);
console.log(reg1.exec(str1));
console.log(reg1.lastIndex);
console.log(reg1.exec(str1));
console.log(reg1.lastIndex);
console.log(reg1.exec(str1));
console.log(reg1.lastIndex);
console.log(reg1.exec(str1));
为了能【一次捕获到所有匹配的】,就在正则原型上写一个方法execAll
RegExp.prototype.execAll = function execAll(str){
str+='';
if(!this.global){
return this.exec(str);
}
let arr = [],
result;
while(result = this.exec(str)){
arr.push(result[0]);
}
return arr;
};
【方法二】 字符串的match方法
String.prototype.match 和正则表达式相结合使用,意思是捕获到当前字符串中,所有符合正则规则的内容
- 【match有本身的局限性(若设置了分组捕获同时又使用了g修饰符)】 :如果正则设置了g修饰符,则基于match捕获的信息只包含大正则匹配的,小分组单独匹配的获取不到;如果没有设置g,则和exec执行的结果是一样的
let str = 'lsw2020happy2021everyday'
reg = /\d+/,
reg1 = /\d+/g;
console.log(str.match(reg1));
console.log(str.match(reg));
【但是match有本身的局限性】eg.身份证的正则处理【拿到对应位数来得到对应的数据】
let id = '210404199504182117';
let reg = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{2})(\d)(?:X|\d)$/g;
let reg1 = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{2})(\d)(?:X|\d)$/;
console.log(id.match(reg));
console.log(id.match(reg1));
正则处理时间字符串

【正则捕获方法2】用正则匹配来实现捕获
- RegExp类上有个静态私有属性$
$& 表示本次test执行得到的匹配结果 RegExp.$&
$1-9 存储的是本次捕获得到的第一个到第九个小分组匹配信息 RegExp.$1~9
let str = 'lsw123lsw'
reg = /\d+/,
reg1= /\d+/g,
reg2 = /(\d)\d+(\d)/g;
reg1.test(str);
console.log( RegExp['$&']);
reg2.test(str);
console.log( RegExp['$&']);
console.log( RegExp['$1']);
console.log( RegExp['$2']);
【正则捕获方法3】用字符串方法Repalce来实现捕获
let str = 'zhenbucuo2020zhenbucuo2021';
str = str.replace('zhenbucuo','真不错');
str = str.replace('zhenbucuo','真不错');
console.log(str);
- 但对于某些需求执行多次replace也是实现不了的
- 在replace的使用中,通常都是配合着正则使用的:找到str中所有和正则匹配的内容,把所有内容依次替换成'想要的内容',但是需要设置修饰符g【改变lastIndex大的值】
let str = 'zbc2020zbc2021';
str = str.replace('zbc','zbcZzsl');
str = str.replace(/zbc/g,'zbcZzsl');
console.log(str);
- 如果replace第二个参数是一个回调函数。第一个参数是一个正则,
- 拿正则和字符串进行匹配,匹配几次,就会把回调函数执行几次
- 不仅把回调函数执行,而且还给回调函数传递了实参信息:
- 把每一次正则匹配的结果 【大正则及小分组正则】 传递给回调函数【实现捕获的一步】
- 回调函数返回什么,就相当于把当前的正则匹配的部分替换成什么
let str = 'zbc2020zbc2021';
str = str.replace(/\d+/g,function(val){
console.log(val);
return '@'+val;
});
console.log(str);
let str = '我的名字是{0},我是一个{1}孩,我今年{2}岁,我喜欢{3}',
arr = ['lsw','男','18','打代码'];
str = str.replace(/\{(\d+)\}/g,function(val,$1){
console.log(arguments);
console.log(val);
return arr[$1];
});
console.log(str);
- 练习题:把单词首字母大写
let str = 'good good study! day day up!',
reg = /\b([a-zA-Z])([a-zA-Z]*)\b/g;
str = str.replace(reg,function(_,$1,$2){
console.log(arguments);
console.log($1);
console.log($2);
return $1.toUpperCase()+$2;
});
- 练习题:日期字符串格式化
let str = '2021-7-6 15:51:8',
arr = str.match(/\d+/g);
reg = /\{(\d+)\}/g,
template = '{0}年{1}月{2}日 {3}时{4}分{5}秒';
template = template.replace(reg,function($1,$2){
console.log($1);
console.log($2);
let val = arr[$2] || '00';
if(val.length<2)val = '0'+val;
return val;
});
字符串处理相关的方法封装
封装一个时间字符串模板
String.prototype.formatTime = function formatTime(template) {
template = template || '{0}年{1}月{2}日 {3}时{4}分{5}秒';
let arr = this.match(/\d+/g);
return template.replace(/\{(\d+)\}/g, (_, $1) => {
let val = arr[$1] || '00';
if (val.length < 2) val = '0' + val;
return val;
});
};
获取URL地址中的:问号传参信息&HASH信息
String.prototype.queryURLParams = function queryURLParams(){
let obj = {};
this.replace(/#([^?=#&]+)/g,(_,$1)=>obj['HASH']=$1);
this.replace(/([^?=#&]+)=([^?=#&]+)/g,(_,$1,$2)=>obj[$1]=$2);
return obj;
}
let url1 = 'http://www.hahahahah.com/?name=LSW&age=18&sex=male#CEO';
console.log(url1.queryURLParams());