直接书写正则表达式
\ 转义字符可以将特殊字符转化为普通字符
[]: 匹配一个字符, [] 内写范围
[^]:取反,匹配该范围之外的
匹配中文:[\u4e00-\u9fa5]
| 表示多个规则之间任选其一
() 单独的一个规则
var reg = /\d+/gim;
^1\d{10}$
^[\u4e00-\u9fa5]{2,6}$
^\w{6,12}$
^\w+@\w+(\.\w+){1,2}$
^\d{4}-\d{7}$
^\d+(\.\d+)?$
^[\d|-\d]+(\.\d+){1}$
^[\d|-\d]+$
创建正则表达式的方式
var reg = /\w+/gi;
var reg = new RegExp(/\w+/,"gi");
var reg = RegExp(/\w+/, "gim");
对象.属性(实例属性),实例属性是属于某个实例对象的私有的属性
类.属性(静态属性),静态属性是所有对公有的属性
var reg = /^(\d|-\d)+$/g;
console.log(reg.test('120'));
// lastIndex是RegExp的静态属性, 表示匹配的开始位置
var reg = /abc/g;
console.log(reg.lastIndex, reg.test('124abc123abc123'))
console.log(reg.lastIndex, reg.test('124abc123abc123'))
console.log(reg.lastIndex, reg.test('124abc123abc123'))
console.log(reg.lastIndex, reg.test('124abc123abc123'))
console.log(reg.lastIndex, reg.test('124abc123abc123'))
console.log(reg.lastIndex, reg.test('124abc123abc123'))
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8xonxxMs-1574150938036)(8B7BF58D72D24E6EB1CEB066A35DFFDE)]
可以看出使用test()函数匹配是循环的,每匹配一次,第二次从上一次匹配结束的下一位进行匹配,直到匹配结束,再从头开始
var reg = /abc/g;
var i = 0;
while(reg.test('124abc123abc123')){
i++;
}
console.log(i); // 2
正则表达式默认情况,使用贪婪模式,即尽可能多的匹配
如果想不使用贪婪模式,需要在量词后添加?
例
var reg = /\d+?/g; // 尽可能匹配少的数字
var s = '123abc123abc123abc';
var reg = /\d+/g;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z3kHcBdV-1574150938036)(2AA181092069445FA1FEAE5D278F26C3)]
var str = '121aba124aba1213aba';
var reg = /\d+/g;
console.log(str.match(reg))// ["121", "124", "1213"]
var str = '1234 djksfj sdklfj sdkfj'
var reg = /[ f]+/g; //按照制空格和字母f进行分割
console.log(str.split(reg)); // ["1234", "djks", "j", "sdkl", "j", "sdk", "j"]
replace第一个参数写正则表达式,第二参数可以为字符串也可以为函数
第二个参数为函数时:函数的第一个参数匹配到的字符串
var str = '\tjavascript\nvue react es6 webpack css3 html5'
var newStr = str.replace(/\s*\b[a-z]/g, function (match) {
if(str.match(/\s*\b[a-z]/)[0] === match) return match.trim();
return match.toUpperCase().trim();
})
console.log(newStr) // javascriptVueReactEs6WebpackCss3Html5
var str = '123213';
var reg = new RegExp(/\d/g,'g');
var i = 0;
var res;
while(res = reg.exec(str)){
i++;
console.log(res[0])
}
console.log(`共匹配${i}次`)
var str = '1大解放路口空间的萨拉克服2十大科技风凉开水3213';
var reg = new RegExp(/[\u4e00-\u9fa5]/g,'g');
var i = 0;
while(reg.test(str)){
i++;
}
console.log(`共有${i}个中文字符`)
// 实现方式1
var str = '1大解放路口空间的萨拉克营销服jiao yi2十大科共产党技风毒凉du开水3213';
var arr = ['共产党', '营销', 'du', '毒','jiao yi'];
for(var i = 0; i < arr.length ; i++){
str = str.replace(new RegExp(arr[i],'g'), '****');
}
console.log(str)
// 实现方式2
var str = '1大解放路口空间的萨拉克营销服jiao yi2十大科共产党技风毒凉du开水3213';
var arr = ['共产党', '营销', 'du', '毒','jiao yi'];
str = str.replace(RegExp(`(${arr.join('|')})+`, 'g'), '****');
console.log(str)
var html =`第1章
第2章
第3章
第4章
第5章第100章第7章`
var reg = /第\d+章/g;
var i = 0;
while(reg.test(html)) i++;
console.log(`共${i}个章节`)
小括号包裹的部分叫捕获组,捕获组会出现在匹配结果中
示例代码
var str = '123abc-789ab-456abc';
var reg = /(\d)+\w+/g;
var res;
while(res = reg.exec(str)){
console.log(res)
}
执行结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ht2XPT53-1574150938037)(F4C34C5C431A4BF187140A3BCB361F32)]
每个被红色方框圈起来的部分就是每一个捕获组的捕获值,也就是我们正则表达式中(\d)匹配到的值。也就是说在一次匹配中捕获组捕获到的值,会从索引1向后依次排列
那么捕获组有什么用呢?看下面的例子
现在有一个需求,给定一个字符串为’2000-10-10,2019-10-14,2019-11-18’, 让我们输出每一个日期,并且输出每一个年月日
var str = '2000-10-10,===2019-10-14/2019-11-18';
var reg = /(\d{4})-(\d{1,2})-(\d{1,2})/g;
while(res = reg.exec(str)){
console.log(`${res[0]} ${res[1]} ${res[2]} ${res[3]}`)
}
// 2000-10-10 2000 10 10
// 2019-10-14 2019 10 14
// 2019-11-18 2019 11 18
打印exec函数匹配结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xiYGIhXe-1574150938038)(29981DFBF9B2496696013DA3B2BD80E1)]
可以看出我们不仅能得到每次匹配的字符串,还可以得到具体匹配的字符串的字串,这就是捕获组的真正作用
我们还可以给每个捕获组命名
命名方式:在每个()内部的最前面写?
,如
// 分别给每个捕获组命名为 year month day
var reg = /(?\d{4})-(?\d{1,2})-(?\d{1,2})/g;
可以通过exec()函数的返回值group对象获取,让我们利用这个特性修改上述代码,可以得到相同的代码
var str = '2000-10-10,===2019-10-14/2019-11-18';
var reg = /(?\d{4})-(?\d{1,2})-(?\d{1,2})/g;
while(res = reg.exec(str)){
console.log(`${res[0]} ${res.groups.year} ${res.groups.year} ${res.groups.year}`)
}
让我们再次打印exec函数匹配结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WcXHAl5t-1574150938039)(A79046E894684CD294AD9DFA07F6EA85)]
可以发现groups内有出现了我们的捕获组,我们发现,原来groups保存的是具名捕获组的值
捕获组的执行是浪费效率的,但捕获又是默认,如果不是特殊需要我们只是想把()内的正则表达式作为一个整体,不想使用捕获功能,那么就需要用到非捕获组
触发方式:在每个()内部的最前面写?:
,如
var reg = /(?:\d{4})-(?:\d{1,2})-(?:\d{1,2})/g;
这样我们就不会再exec执行结果看见捕获组了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G2HCNf6S-1574150938039)(2F661DF8FE514AC2AA62356D464CA906)]
var str = '2000-10-10-4,===2019-10-14-5/2019-11-6-18~2019-11-18';
var reg = /(\d{4})-(\d{1,2})-(\d{1,2})-(\d{1,2})/g;
str.replace(reg, function (match, g1, g2, g3, g4,index, self) {
console.log(...arguments)
})
// 这里正则表达式中有四个捕获组
// 函数从第1个到第1+4个参数就为捕获组捕获到的值
// 剩下两个参数为匹配的起始位置和输入的字符串
捕获组用$1、$2、$3
表示,如
var str = '2000-10-10-4,===2019-10-14-5/2019-11-6-18~2019-11-18';
var reg = /(\d{4})-(\d{1,2})-(\d{1,2})-(\d{1,2})/g;
str.replace(reg, '年$1月$2日$3小时$4')
正则表达式中使用某个数组,使用方式:\捕获组编号
或\k
查找出’aaaaabbbbbddddddddddcccccdewdddkkkk’中出现的连续字符
// 非具名捕获组
var str = 'aaaaabbbbbddddddddddcccccdewkkkk';
var reg = /(\w)\1+/g;
while(res = reg.exec(str)){
console.log(res[1])
}
// 具名捕获组
var str = 'aaaaabbbbbddddddddddcccccdewkkkk';
var reg = /(?\w)\1+/g;
while(res = reg.exec(str)){
console.log(res.groups.char)
}
检查某个字符串是否满足某个规则,该规则不成为匹配结果也不成为捕获组
这个规则
的就叫正向断言,使用方式为(?=)
面试题
用正则表达式将’1123123123123’转换为’1,123,123,123,123’
var str = '123123123123'
var reg = /\B(?=(\d{3})+$)/g; // 断言内的所有()都不会成为匹配结果与捕获组
console.log(str.replace(reg, ','));
检查某个字符串是否满足某个规则,该规则不成为匹配结果也不成为捕获组
这个规则
的就叫反向断言,使用方式为(?!)
实际应用题
密码强度判断
function jugdePWD(pwd){
if(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*.]).{6,12}$/.test(pwd)){
return '强'
}else if(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{6,12}$/.test(pwd)){
return '中'
}else if (/^(?=.*[a-z])(?=.*[A-Z]).{6,12}$/.test(pwd)){
return '弱'
}else {
return '不满足条件'
}
}
console.log(jugdePWD('AAAAAi1$'));