1、基于exec的捕获
/**
* 1、基于exec的捕获
* 1.捕获到的结果是null或者是一个数组
* 1).第一项是本次捕获到的内容
* 2).第二项是index 表示当前捕获到的字符串在整个字符串中的索引位置
* 3).第三项是 input 原始字符串
* 2、每执行一次,我们就会获取到一个符合正则规则的结果,但是默认情况(懒惰)下我们就算执行100遍也只会获取到第一个匹配到的结果
*/
let str = "dd231hj1312h31j2b3j12k31j2b31j2";
let reg = /\d+/;
let result = reg.exec(str);
console.log("result:", result, result[0]); // => [ '231',index: 2, input: 'dd231hj1312h31j2b3j12k31j2b31j2', groups: undefined ] '231'
lastIndex:当前正则下一次匹配的起始索引位置
/**
* reg.lastIndex
* 当前正则下一次匹配的起始索引位置
*/
let str = "das131hj123hjk";
let reg = /\d+/g;
// 当正则设置全局匹配修饰符g之后,lastIndex会自动的修改到新的索引起始位置
console.log(reg.lastIndex); // => 0
console.log(reg.exec(str)); // => ['131',...]
console.log(reg.lastIndex); // => 6 下一次从索引为6的地方开始匹配
console.log(reg.exec(str)); // => ['123',...] 第二次捕获,捕获到123
console.log(reg.lastIndex); // => 11 下一次从索引为11的地方开始匹配
// 没有匹配到结果后,会返回null , 但是lastIndex又会变为0,再次捕获又会从第一个开始捕获
console.log(reg.exec(str)); // => null 没有捕获到东西
console.log(reg.lastIndex); // => 0
注意: 正则的懒惰性:默认情况下lastIndex的值是不会修改的,每一次都是从字符串的开始位置进行查找,所以找到的永远是第一个
解决懒惰性 => 添加全局修饰符:g
自定义一个exec的全部捕获方法
/**
* 为了解决exec只能捕获一次,我们可以编写一个函数来一次性把所有的结果都捕获到
* 前提:正则必须设置全局修饰符 g
*/
function execAll(str) {
// str => 要捕获的字符串
// 一进来要先判断当前正则是否有全局修饰符参数,没有设置就不能进行循环捕获了,不然会导致死循环
if (!this.global) {
// 如果没有全局修饰符
return this.exec(str);
}
let arr = [],
res = this.exec(str);
while (res) {
arr.push(res[0]);
// 只要捕获结果不为null,那么就继续捕获下去
res = this.exec(str);
}
return arr;
}
RegExp.prototype.execAll = execAll;
let text = "123h34hj23k123jk234";
let reg3 = /\d+/g;
console.log("reg3", reg3.execAll(text)); // => [ '123', '34', '23', '123', '234' ]
也可以使用match来进行全部匹配
正则捕获的贪婪性
/**
* 正则捕获的贪婪性
* 默认情况下,正则是按照当前所能匹配的最长的结果来进行获取的,当设置了+ 和 * 时
*/
let text = "sda1231k121h231h21l123j2";
let reg = /\d+/g;
console.log(text.match(reg)); // => [ '1231', '121', '231', '21', '123', '2' ]
// 在量词元字符后面设置了 ? => 取消捕获时的贪婪性(按照正则匹配的最短结果来获取)
let reg2 = /\d+?/g;
console.log(text.match(reg2)); //[ '1','2','3','1','1','2','1',... ]
- 在正则中 ? 的作用
- 问号左边是非量词元字符:本身代表量词元字符,出现零到一次
- 问号左边是量词元字符:取消捕获时候的贪婪性
- (?:) 只匹配,不捕获
- (?=) 正向查找
- (?!) 负向查找
test捕获
// 其它捕获方式 test => test也能捕获 ,本意是匹配
let str = "{0}年{1}月{2}日";
let reg = /\{(\d+)\}/g;
console.log(reg.test(str)); // => true
console.log(RegExp.$1); // => 0 存储的是上一次捕获的值
console.log(reg.test(str)); // => true
console.log(RegExp.$1); // => 1 存储的是上一次捕获的值
console.log(reg.test(str)); // => true
console.log(RegExp.$1); // => 2 存储的是上一次捕获的值
replace方法使用
// replace方法
/**
* 1、使用replace方法处理时间字符串
*/
let time = "2020-12-23";
// 变为2020年12月23日
let reg = /^(\d{4})-(\d{1,2})-(\d{1,2})$/;
// let newTime = time.replace(reg, "$1年$2月$3日");
// console.log(newTime); // => 2020年12月23日
// 还可以这么处理 time.replace(reg,[function])
// 这样子首先会把reg和time来进行匹配,匹配几次后面的回调函数就会执行几次
time = time.replace(reg, function (str, $1, $2, $3) {
console.log($1, $2, $3); // => 2020 12 23
});
replace方法练习:
//replace 方法练习 => 让英文首字母大写
let english = "hello world, my name is jerry";
let reg2 = /\b([a-zA-Z])[a-zA-Z]*\b/g; // => \b 用来匹配单词的边界
// 回调函数会执行六次,每一次都会把捕获到的结果传递给函数
english = english.replace(reg2, function (...arg) {
let [content, $1] = arg;
$1 = $1.toUpperCase();
content = content.substring(1);
return $1 + content;
});
console.log(english); // => Hello World, My Name Is Jerry
/**
* js正则中\b的用法
* \b用来匹配单词的边界,即\w和\W之间的位置,或字符串首位与\w或\w与字符串末尾的位置。
*/
let str = "aa bb cc dd";
let reg3 = /\b\w+\b/g;
console.log(reg3.exec(str)); //aa
console.log(reg3.exec(str)); //bb
console.log(reg3.exec(str)); //cc