转义字符
let str = '<div>a</div>\
<div>b</div>'
console.log(str); // js只允许当行字符串,这里的 \ 是把后面的空格转义
\n 换行
\r 回车
\t
正则的两种写法及应用
var reg = new RegExp('abc', 'igm');
var reg = /abc/igm;
应用:一般使用对象字面量(第二种)
let rule = 'abc';
var reg = new RegExp(rule, 'igm'); // 要使用变量的情况下就要使用第一种情况,因为对象字面量会把rule当作一个字符串
正则修饰符/正则属性
- i: 忽略大小写
- g:全局匹配
- m: 多行匹配
const reg = /^test/;
const str = 'abcasfdas \ntestasdasd';
console.log(reg.test(str)); // false
const reg2 = /^test/m;
console.log(reg2.test(str)); // true
方括号[] 参考: https://www.w3school.com.cn/jsref/jsref_obj_regexp.asp
[abc]: 取abc中的任意一个
[^abc]: 取非abc的任意一个, ^ 在 [] 是 非 的意思
/abc|123/g: 取 abc 或者 123
练习:我们要匹配 abc 或者 123 后再跟一位字母 q
/abc|123q/g //这样写是错误的,会匹配为 abc 或者 23q
/(abc|123)q/ // ()会提升优先级,先执行()里面的
量词 参考: https://www.w3school.com.cn/jsref/jsref_obj_regexp.asp
参考文档很详细,这里不多描述,只讲一些注意点
var str = "abcd";
var reg = /\w+/g;
var reg = /\w*/g;
console.log(str.match(reg)); // ["abcd"]
console.log(str.match(reg2)); // ["abcd", ""] *是0到多次,匹配到 abcd 后,还会匹配一次 ""
练习
var str = "abcd";
var reg = /\d*/g;
console.log(str.match(reg)); // ["", "", "", "", ""]
var str = "abcd";
var reg = /\w?/g;
console.log(str.match(reg)); // ["a", "b", "c", "d", ""]
子表达式,反向引用 (\n) ()除了提升权重外,还表示子表达式
let str = 'aabbbbaaaabbbbwxxxxiaaaa';
let reg = /(a)(b)\2\2\2/g; // \n的n并不是数量,而是第几个引用,这里\1引用的就是a,\2引用就是b
console.log(str.match(reg));
let reg2 = /(\w)\1\1\1/g; // 这样可以匹配到所有 aaaa bbbb cccc 这种格式
console.log(str.match(reg2));
let reg3 = /(\w)\1(\w)\2/g; // 这样可以匹配到所有 aaaa bbbb cccc 这种格式
console.log(str.match(reg3)); // 匹配 aabb xxyy 这种格式
贪婪模式和非贪婪模式
{
let str = "abc{{name}}safds{{age}}";
let reg = /{{(.*)}}/g;
console.log(reg.exec(str)); // "{{name}}safds{{age}}" 贪婪匹配,
let reg2 = /{{(.*?)}}/g;
console.log(str.match(reg2)); // ["{{name}}", "{{age}}"] ?表示0或一次,但是在一些不是具体的量词(如+?*)后面表示 非贪婪匹配,能少匹配就不会多匹配
}
{
let str = 'abcds';
let reg = /\w??/g;
console.log(str.match(reg)); // ["", "", "", "", "", ""]
}
属性
- global:正则是否设置了全局匹配,return Boolean
- ignoreCase
- multiline]
- source : 返回正则的匹配规则
- lastIndex:一个整数,标示开始下一次匹配的字符位置。(与exec中结合讲解)
方法
- test() return Boolean
- exec()
全局匹配的情况下
let str = 'ababab';
let reg = /ab/g;
console.log(reg.lastIndex); // 0
console.log(reg.exec(str)); // ["ab", index: 0, input: "ababab", groups: undefined]
console.log(reg.lastIndex); // 2
console.log(reg.exec(str)); // ["ab", index: 2, input: "ababab", groups: undefined]
console.log(reg.lastIndex); // 4
console.log(reg.exec(str)); // ["ab", index: 4, input: "ababab", groups: undefined]
console.log(reg.lastIndex); // 6 // 这里是6的原因是开始下一次匹配的字符位置
console.log(reg.exec(str)); // null
console.log(reg.lastIndex); // 0
console.log(reg.exec(str)); // ["ab", index: 0, input: "ababab", groups: undefined]
// 可以发现 reg.lastIndex 标示开始下一次匹配的字符位置,和 exec() 匹配结果中的 index 几乎一样
// 而 reg.lastIndex 属性是可以修改的,我们修改一下试试
console.log('-----------------------');
reg.lastIndex = 4;
console.log(reg.lastIndex);
console.log(reg.exec(str)); // 可以发现 reg.lastIndex 的修改会影响 exec 的匹配结果,exec会从reg.lastIndex处开始匹配
// 如果我们修改一个不刚好匹配的值呢
console.log('+++++++++++++++++++++++++');
reg.lastIndex = 1;
console.log(reg.lastIndex); // 1
console.log(reg.exec(str)); // ["ab", index: 2, input: "ababab", groups: undefined]
console.log(reg.lastIndex); // 4
console.log(reg.exec(str)); // ["ab", index: 4, input: "ababab", groups: undefined]
// reg.lastIndex 会根据 exec 的匹配结果进行修正
{
let str = "aabbccaadd";
let reg = /(\w)\1(\w)\2/g;
console.log(reg.exec(str)); // ["aabb", "a", "b", index: 0, input: "aabbccaadd", groups: undefined]
// aabb就是匹配到的字符串, 'a' 'b' 就是子表达式, index解释过,input就是str
}
非全局匹配:匹配的永远是第一个,且修改lastIndex无效
{
let str = "abc";
let reg = /\w/;
console.log(reg.exec(str));
console.log(reg.exec(str));
reg.lastIndex = 2;
console.log(reg.exec(str));
}
支持正则表达式的 String 对象的方法
- match
区别:
match
- 加 g ,返回一个类数组,数组中的每一项是匹配的值
- 不加 g,匹配的和 exec 一置,永远返回第一个匹配的结果,且修改reg.lastIndex不会对其匹配照成影响
exec
- 加 g,执行一次匹配一次,与lastIndex相互影响
- 不加 g,和match一致
- split
- replace
{
let str = 'jsplusplus';
let res = str.replace('plus', '+'); // replace(regexp/substr,replacement) param1: 被替换的, param2:替换后的
console.log(res); // js+plus replace并没用全局匹配的能力 相当于 str.replace(/plus/, '+');
}
{
let str = "aabbccdd"; // 替换为 bbaaddcc
let reg = /(\w)\1(\w)\2/g;
let res = str.replace(reg, '$2$2$1$1'); // $1就是子表达式\1的那个值, 这里的reg匹配到str有 aabb ccdd 将aabb替换为bbaa, ccdd替换为ddcc
console.log(res);
// 方式二
str.replace(reg, ($, $1, $2) => {
console.log($, $1, $2); // aabb a b ccdd c d $:匹配的字符串 $1,$2:子表达式的值
return $2 + $2 + $1 + $1;
});
}
{
// 练习
let str = "js-plus-plus"; // 变为 jsPlusPlus
let reg = /-(\w)/g; // 这里的$1匹配的是子表达式,必须要加()
let res = str.replace(reg, ($, $1) => {
return $1.toUpperCase();
});
console.log(res);
}
{
// 练习
let str = "jsPlusPlus"; // 变为 js-plus-plus
let reg = /(P)/g;
let res = str.replace(reg, ($, $1) => {
return '-' +$1.toLowerCase();
});
console.log(res);
}
{
// 练习 xxyyzz => XxYyZz
let str = "xxyyzz";
let reg = /(\w)\1/g;
let res = str.replace(reg, ($, $1) => {
return $1.toUpperCase() + $1;
});
console.log(res);
}
{
// 练习 aabbcc => a$b$c$,不使用function方式
let str = "aabbcc";
let reg = /(\w)\1(\w)\2(\w)\3/g;
let res = str.replace(reg, '$1$$$2$$$3$$'); // 要使用$,必须写两个$,因为$有特殊含义
console.log(res);
}