初识正则表达式
华为前端全栈第二阶段马上就结束了,希望第三阶段框架部分可以讲的深入一些,结合一些实战项目和综合应用场景,可以让我们这些小白迅速上手。
最近发现前端部分还是一块内容正则表达式也是很重要,今天分享出来
初识正则表达式:(regular expression)RegExp
用来处理字符串的规则
只能处理字符串的规则
它是一个规则:可以验证字符串是否符合某个规则(test),也可以把字符中符合规则的内容捕获到(exec/match...)
let str="good good study,day day up!";
let reg=/\d+/;//是否包含数字
reg.test(str);//false
str='2019-08';
reg.exec(str);
编写正则表达式:
字面量创建方式:(两个斜杠之间包起来的,都是用来描述规则的元字符)
let reg=/\d+/;
构造函数模式创建:两个参数:元字符串,修饰符字符串
let reg=new RegExp(“\\d+”);
正则表达式由两部分组成:
元字符:
1、量词元字符:设置出现的次数
*:零到多次
+:一到多次
?:零次或者一次
{n}:出现n次
{n,}:出现n到多次
{n,m}:出现n到m次
2、特殊元字符:单个或者组合在一起代表特殊的含义
\:转移字符(普通-特殊-普通)
. :除\n(换行符)以外的任意字符
^:从哪一个元字符作为开始
$:以哪一个元字符作为结束
\n:换行符
\d:0~9之间的一个数字
\D:非0~9之间的一个数字(大写和小写的意思是相反的)
\w:数字、字母、下划线中的任意一个字符
\s:一个空白字符(包含空格、制表符、换页符等)
\t:一个制表符(一个tab键:四个空格)
\b:匹配一个单词的边界
x|y:x或者y中的一个字符
[xyz]:x或者y或者z中的一个字符
[^xy]:除了x/y以外的任意字符
[a-z]:指定a-z范围中的任意字符 [0-9a-zA-Z]===\w
[^a-z]:上一个取反“非”
():正则中的分组符号
(?:):只匹配不捕获
(?=):正向预查,=后面必须跟xxx
(?!):负向预查,!后面必须不跟xxx
3、普通元字符:代表本身含义
/xiaoyao/:次正则匹配的就是“xiaoyao”
([a-z])\1:让第一次分组的字符再次出现一次
修饰符:img
i:ignoreCase 忽略单词大小写匹配
m:multiline 可以进行多行匹配
g: global 全局匹配
/A/.test('lala') //false
/A/i.test('lala') //true
元字符详细解析:
^ $
let reg=/^\d/; //数字开头为true
reg.test("xiaoyao");//false
let reg=/\d$/; //数字结尾为true
console.log(reg.test("xiaoyao2020")); //true
let reg=/\d+/; //包含数字即可
let reg=/^\d+$/; //字符串只能是和规则一致的内容
let reg=/^1\d{10}$/; //验证手机号码
转义字符:
let reg = /^2.3$/;
reg.test('2.3'); //true
reg.test('2@3'); //true
reg.test('23'); //false
let reg = /^2\.3$/;
reg.test('2.3'); //true
reg.test('2@3'); //false
let str="\\d";
reg=/^\d$/;
console.log(reg.test(str));// false
reg=/^\\d$/;
console.log(reg.test(str)); // true
x|y:
let reg = /^18|19$/; //直接x|y会存在很乱的优先级问题,一般用小括号处理:
reg.test("189")// false
let reg = /^(18|19)$/; //只能是18或19中的一个
reg.test("189")// false
reg.test("29")// false
[]:
1、中括号中出现的字符一般都代表本身的含义
let reg=/^[@+]+$/;
reg.test("@"); //true
reg.test("@@"); //false //只能匹配一位
reg=/^[\d]$/; //\d在中括号中还是0-9
reg.test("d"); //false
reg.test("4"); //true
2、中括号中不存在多位数
reg=[/^[18]$/;
reg.test("1"); //true
reg.test("18");//false
正则两种创建的区别:
//构造函数因为传递的是字符串,\需要写两个才代表斜杠
let reg=/\d+/g;
reg=new RegExp("\\d+","g");
//正则表达是中的部分内容是变量存储的值
1、两个斜杠中间包起来的都是元字符(如果正则中要包含某个变量的值,则不能使用字面量方式创建)
let type="xiaoyao";
reg=/^@"+type+"@$/;
reg.test("@xiaoyao@");//false
reg.test('@"""typeee"@');//true
2、这种情况只能使用构造函数方式(因为它传递的是规则是字符串,只有这样才能进行字符串拼接)
reg=new RegExp("^@"+type+"@$");
reg.test("@xiaoyao@");//true
正则的捕获:
实现正则捕获的方法:
正则RegExp.prototype上的方法:
exec:
实现正则捕获的前提是:当前正则要和字符匹配,如果不匹配捕获的结果是null
基于exec实现正则的捕获:
1、捕获到的结果是null或者一个数组
数字第一项:本次捕获到的内容
其余项:对应小分组本次单独捕获的内容
index:当前捕获内容在字符串中的起始索引
input:原始字符串
2、每执行一次exec,只能捕获到一个符合正则规则的,但是默认情况下,获取的结果永远都是第一个匹配的,其余的捕获不到(“正则捕获的懒惰性”:解决办法:全局修饰符g)
懒惰性的原因:默认情况下lastIndex的值不会被修改,每一次都是从字符串开始位置查找,所以找到的永远只是第一个
let str="xiaoyao2019yangfan2020qihang2021";
reg.exec(str);//["2019",index:7,input:"xiaoyao2019yangfan2020qihang2021"];
reg.lastIndex:当前正则下一次匹配的起始索引位置
reg.lastIndex;//0
let reg=/\d+/g;
设置全局匹配修饰符g后,第一次匹配完,lastIndex会自己修改,全部捕获后,再次捕获的结果是null,但是lastIndex又回归了初始值零,再次捕获又从第一个开始了
let reg=/\d+/g;
if(reg.tset(str)){
//验证:只有正则和字符串匹配我们再捕获
console.log(reg.lastIndex);//基于test匹配验证后,lastIndex已经被修改为第一次匹配后的结果,所有下一次捕获不再从头开始了
console.log(reg.exec(str));
}
需求:编写一个方法execAll,执行一次可以把所有匹配的结果捕获到(前提正则一定要设置全局修饰符)类似于match的源码
~function(){
function execAll(){
//str:要匹配的字符串
//this:RegExp的实例
//进来的第一件事,验证当前正则是否设置了g,不设置则不能在进行循环捕获,否则会导致死循环
if(!this.global) {return this.exec(str)};
//arg存储最后所有捕获的信息,res存储每一次捕获的内容[数组]
let ary=[],
res=this.exec(str);
while(res){
//把每一次捕获的内容res[0]存放到数组中
ary.push(res[0]);
//只要捕获的内容不为null,则继续捕获
res=this.exec(str);
}
return ary.length ===0?null:ary;
}
RegExp.prototype.execAll=execAll;
}();
字符串中的match方法,可以在执行一次的情况下,捕获到所有匹配的数据(前提:正则也得设置g才可以)
console.log("珠峰2019@2020培训".match(reg));
test:
let str="xiaoyao2019yangfan2020qihang2021";
let reg=/^\d+$/;
reg.test(str);//false
reg.exec(str);//null
- 点赞
- 收藏
- 关注作者
评论(0)