正则匹配
文章目录
我们为什么要学习正则匹配
//需求:我们需要提取字符串里面的连续数字,然后返回一个数组
//如果使用自定义函数的方式
let getNumber = (str) => {
let temp = "";
let arr = [];
// 我们首先来循环这个字符串拿到所有的数字字符
for (let i = 0; i < str.length; i++) {
// 如果不是一个数字就返回
if (!isNaN(str[i])) {
//如果是一个数字那么就再组装一下
temp += str[i];
} else {
//如果下一个不是一个数字了那么就把temp放在数组里面
//过滤为空的项
if (temp !== "") arr.push(temp);
temp = "";
}
}
//如果最后一项是数字,添加到输出的数组里面
if (temp !== "") arr.push(temp);
return arr;
};
let result = getNumber(str);
console.log(result);
使用正则匹配
//但是我们通过正则表达式就可以很简单的做到这件事
let reg = /\d+/g; //定义匹配规则
let arr = str.match(reg);
console.log(arr);
//是一样的效果
console.log(isNaN(2));
正则的两种创建方法
字面量创建
注意事项:在字面量创建的匹配规则/ /里面不能解析变量任何在里面的字符,都会被解析成匹配规则
//1. 字面量创建
let str = "Asdasdada223asdada";
let reg = /\d+/g;
//我们就可以在字符串下面调用match方法进行匹配
let arr = str.match(reg);
//但是这种方法不支持变量的形式
/* let abc =123
let reg=/\abc/g //这只能解析成单个字符,无法解析成123 */
通过RegExp创建
通过 let reg2 = new RegExp("\d+", “g”);来创建一个匹配规则
注意的事,第一个参数如果匹配\d \w这些东西,那么需要加上转义字符,然后两个参数第一个是匹配规则,第二个是匹配范围,默认单个匹配,因为第一个参数是参数形式所以可以定义变量
//2.构造函数创建
let str2 = "Asdasdada223asdada";
// let reg2=new RegExp("\d+","g");
// 但是上面这个是不行的这个只会匹配到全局的所有字母d
// 我们需要在匹配的基础上再进行转义一下
let reg2 = new RegExp("\\d+", "g");
//这里是可以用变量的
// 我们定义一个abc
let abc = "12312";
let reg3 = new RegExp(abc, "g");
let result = str2.match(reg2);
console.log(result2);
可以使用正则的一些常用方法
正则对象下面的方法
test 判断有没有匹配到相应的字符
let str = "abc123fda123";
// let reg = /\d+/g;
let reg = /efg/g;
//如果匹配到,那么返回true,如果没有返回false
console.log(reg.test(str));
exec 有点像generator构造器的一个方法
let str = "abc123fda1234";
let reg = /\d+/g;
//第一次调用返回123
console.log( reg.exec(str) )
//会记录当前的lastIndex然后下一次执行exrc的时候会从当前的位置开始
console.log(reg.lastIndex);
//第二次调用的时候会返回1234
console.log( reg.exec(str) )
//当调用完成之后,后面没有匹配项的时候,那么会返回null
console.log( reg.exec(str) )
字符串方法
split
//split 方法
let str = "abc123fda1234rt";
// let arr = str.split(1);
let arr = str.split(/\d+/);
console.log(arr) //["abc", "fda", "rt"]
search
let str = "abcdefghiejk";
// let reg = /e/g;
let reg = /z/;
//如果匹配到了那么就返回对应的下标,
//如果没有匹配到,那么就会返回-1
console.log(str.search(reg));
match
let str = "abc11defghiej222k";
let reg = /\d+/g;
console.log( str.match(reg) );
replace
let str = "abc11defghiej222k";
let reg = /\d/g;
// console.log( str.replace(reg,"*") );
let res = str.replace(reg,function(arg){
//第二个参数为一个函数,实现更多自定义的功能
console.log(arg)
return "*"
})
console.log(res);
元字符(有特殊含义的的非字母字符)
字符相关的元字符
\w \W \d \D \s \S .
- \w :数字、字母、下划线;
- \W :非数字、字母、下划线;
- \s :匹配空格;
- \S :匹配非空格
- \d :匹配数字
- \D:匹配非数字
- . : 非 \n \r \u2028 \u2029
// \w :数字、字母、下划线;
// let str = "~123fdfs";
// let reg = /\w+/g;
// console.log( reg.test(str));
// \W :非数字、字母、下划线;
// let str = "123fdfs";
// let reg = /\W+/g;
// console.log( reg.test(str));
// \s :匹配空格;
// let str = "abcfdsadfs";
// // let reg = /\s+/g;
// let reg = /\S+/g;
// console.log( reg.test(str));
// . : 非 \n \r \u2028 \u2029;
// let str = "\r";
let str = `afb`
let reg = /a.b/;
console.log( reg.test(str));
数量相关的元字符
{} ? + *
- {} 定义一个左闭右闭的区间,右面没有值就说明是正无穷,如果只有一个值的话就说明重复几次
- ? 0个或者是1个 相当于 {0,1}
- "+"一个或者多个 相当于 {1,}
- "*"任意个 相当于 {0,}
let str = "abceeeeeeeeeeeffd";
// let reg = /ce{3}/g; //匹配三个e true
// let reg = /ce{1,4}/g; //匹配1-4个e true
// let reg = /ce{1,}f/g //匹配1-无穷多个e true
console.log(reg.test(str));
?的另一个作用
let str = "123456789";
// let reg = /\d{2,4}/g; //贪婪匹配 会匹配四个字符
let reg = /\d{2,4}?/g; // 惰性匹配; 会匹配两个字符
let res = str.match(reg);
console.log(res);
位置相关的元字符
^ $ \b \B
- ^ :开头
let str = "abedef";
let reg = /^\w/g;
let res = str.replace(reg, "*"); //*bedef 如果没有\w 那么就是*abedf
console.log(res);
- $:结尾
- \b :边界符(只要不是\w(字母数字下划线)的都是边界符)
let str = "this is a book";
let reg = /\bis\b/g;
let res = str.match(reg); //["is"]
console.log(res);
- \B: 非边界符
let str = "this is a book";
let reg = /\B\w{2}\b/g;
let res = str.match(reg);
console.log(res); //["is","ok"]
括号相关
() [] {}
- () :分组 提取值 替换值 反向引用
分组
let str = "abababfdsafds";
let reg = /(ab){3}/g;
console.log(reg.test(str));
提取值
let str = "2020-01-02";
let reg = /(\d{4})-(\d{2})-(\d{2})/;
// console.log( );
str.match(reg)
console.log(RegExp.$1)
console.log(RegExp.$2)
console.log(RegExp.$3)
替换
let str = "2020-01-02"; // 01/02/2020
let reg = /(\d{4})-(\d{2})-(\d{2})/;
// let res = str.replace(reg,"$2/$3/$1");
let res = str.replace(reg,function(arg,year,mouth,date){
return mouth +"/" + date + "/" +year;
});
console.log(res)
反向引用
// 反向引用;
//需求就是我们需要后面的下划线和前面的下划线是同一个类型的
let className = "news-container-nav"; //news_container_nav
let reg = /\w{4}(-|_)\w{9}(\1)\w{3}/;
let res = reg.test(className);
console.log(res);
- {} 范围
- [] 字符集合
let str = "My name is LiLei";
// let reg = /Li[Ll]ei/g; //这里面是或者的关系
// [a-z] [A-Z]; [a-Z] //也可以这样使用
// let reg = /[0-9]/g;
// console.log( reg.test(str));
let reg = /[^0-9]/g; //如果在字符集合里面使用^ 表示取反,就是非的意思
console.log( reg.test(str));
//\d [0-9]; \w [a-zA-Z0-9_]; //下面的特殊元字符可以用集合的形式来表示
匹配模式
g i m s u y;
- g 全局匹配
g:全局匹配;
let str = "abc123fdaf123fdasf";
let reg = /\d+/g;
let res = str.match(reg);
console.log(res);
- i:忽略大小写
let str = "abcABc";
let reg = /ABC/gi;
console.log(reg.test(str));
- m:多行模式
let str = `abc
efg
hij`;
let reg = /^\w/gm;
let res = str.replace(reg,"*");
console.log(res);
/*
*bc
*fg
*ij
*/
- s: "."非 \n \r \u2028 \u2029 这种方法可以忽略换行符号
let str = `abc
efg`;
let reg = /^a.*g$/gs;
console.log( reg.test(str));
- u 匹配unicode编码
// u:匹配unicode编码;
let str = "a";
let reg = /\u{61}/gu;
console.log(reg.test(str));
- y 粘性模式
let str = "12345fdafdsa4324";
let reg = /\d/gy;
console.log( reg.exec(str));
console.log( reg.exec(str));
console.log( reg.exec(str));
console.log( reg.exec(str));
console.log( reg.exec(str));
console.log( reg.exec(str));
命名分组以及零宽断言
- 命名分组
let str = "2020-01-06";
let reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
console.log( str.match(reg)); //下面会有一个group属性,里面会有自己定义的一些变量,year,month,day
- 零宽断言
//正向零宽断言
let str = "iphone3iphone4iphone5iphonenumber";
// 肯定
// let reg = /iphone(?=\d)/g; //苹果3苹果4苹果5iphonenumber
// 否定
let reg = /iphone(?!\d)/g;
let res = str.replace(reg,"苹果");
console.log(res);
//负向零宽断言;
let str = '10px20px30pxipx';
// 肯定
// let reg = /(?<=\d+)px/g; //10像素20像素30像素ipx
// 否定
let reg = /(?<!\d+)px/g;
let res = str.replace(reg,"像素"); //10px20px30pxi像素
console.log(res);