正则表达式
基本
[]
这里面的某个字符匹配,注意里面的比如0-9
a-z
不能降序填写,放置在里面的内容会当作字符处理,比如[.+]
会匹配.
或+
{}
限定数量^
放在首部,开头匹配$
放在尾部,尾部匹配,起始和结束可以用于匹配所有字符数量是否相等[^]
表示非\数字
表示必须第几个原子组匹配的内容相同,- 嵌套分组时当括号套括号数的话就从左往右数,第几个左括号就是第几个原子组
- 不记录分组
(?:)
表示忽略当前组(?<name>)
可以给原子组起别名,通过$<name>
访问,原子组一般通过$num
访问,别名可以增加标识符(?:str)
先行断言,可以理解为条件,需要后面为对应的字符(str)才匹配(?<=str)
后行断言,需要前面为对应的字符(str)才匹配(?!str)
零宽负向先行断言,后面不是什么才匹配(?<!str)
零宽负向后行断言,前面不是什么才匹配
反斜杠
-
\s
由于匹配空白,它会匹配空格\n
-
\w
匹配字母数字下划线,包括\d
,\W
则相反 -
\p
可以使用字符属性来匹配字符,需要和描述符u
一起使用
let hd = "hou 2010";
// 下面的 \p{L} 表示匹配字母,L 可以换为其他类型
// http://cldr.unicode.org/unicode-utilities/list-unicodeset
console.log(hd.match(/\p{L}/gu)); // ['h', 'o', 'u']
模式
-
g
描述符在使用match
时会从头匹配到尾,但是后面的属性没有 -
s
描述符中.
可以匹配换行符 -
i
描述符,大小写都匹配 -
m
描述符,多行匹配 -
u
表示按unicode(utf-8)
匹配,主要针对多字节比如汉字 -
y
表示在多次匹配时,不会忽略不能匹配的字符,在连续匹配的时候比如g
效率更高,因为g
所有字符都会尝试匹配
let hd = "后盾人QQ群:11111111,99999999,888888888我的看看";
let reg = /(\d+),?/y;
// 从头匹配并不行
reg.lastIndex = 7;
while ((res = reg.exec(hd))) qq.push(res[1]);
console.log(reg.exec(hd));
方法
字符串
-
match
如果没有g
只会匹配一次,如果有g
则不会有剩余的属性,比如index
,groups
-
search
接受一个正则来进行检索,输出索引 -
replace
可以接受一个正则和一个替换的字符串
// 可以用 $数字 来表示匹配的原子组
let hd = "(010)999999999 (020)8888888";
let reg = /\((\d{3,4})\)(\d{7,8})/g;
console.log(hd.replace(reg, "$1-$2")); // 010-999999999 020-8888888
// 可以用 $& 表示匹配的字符本身
let he = "=后盾人=";
console.log(hd.replace(/后盾人/, "$&9")); // =后盾人9=
// $% 表示匹配部分前面的字符
console.log(hd.replace(/后盾人/, "$`")); // ===
// $' 表示匹配部分后面的字符
console.log(hd.replace(/后盾人/, "$'")); // ===
-
split
可以接受一个字符串或是正则 -
matchAll
可以得到一个迭代对象保存所有匹配的结果
// 低端浏览器实现 matchAll
String.prototype.matchAll = function (reg) {
let res = this.match(reg);
if (res) {
let str = this.replace(res[0], "^".repeat(res[0].length));
let match = str.matchAll(reg) || [];
return [res];
}
};
正则
-
test
返回 boolean -
exec
也是只匹配一次,如果是g
也就是全局模式下,它会有lastIndex
属性,下次执行会从lastIndex
处开始匹配
// exec 全局匹配
let str = "shishi";
// 注意必须是在全局模式下
let reg = /u/gi;
let result = [];
while ((res = reg.exec(str))) {
result.push(res);
}
console.log(result);
概念
- 贪婪匹配,即匹配更多的更好
let hd = "hddddd";
console.log(hd.match(/hd+/)); // hddddd
console.log(hd.match(/hd{1, 3}/)); // hddd
// 禁止贪婪
let hd = "hdddd";
// 后面加问号时它的匹配长度向一倾斜
console.log(hd.match(/hd+?/)); // hd,
console.log(hd.match(/hd{2}?/)); // hdd
a.match(/(.\.)+/g); // ["1.2.3."]
a.match(/(.\.)+?/g); // ["1.", "2.", "3."]
一些技巧
-
匹配所有字符
[\s\S]``[\d\D]
都可以匹配所有字符 -
批量使用正则进行密码强度校验
input.addEventListener("keyup", (e) => {
const value = e.target.value;
const regs = [
/^[a-z0-9]{5,10}$/i,
/[A-Z]/, // 必须有大写字母
/0-9/, // 必须有数字
];
let state = regs.every((e) => e.test(value));
console.log(state);
});
- 模糊电话号码
let users = `
向军电话:123456789
后盾人电话: 987654321
`;
let reg = /(?<=\d{7})\d{4}/gi;
users = users.replace(reg, (v) => {
return "*".repeat(4);
});
console.log(users);
- 用户名关键字
const reg = /^(?!.*向军.*).*/i;
console.log(this.value.match(reg));
一些问题
- 有时使用
new
创建正则会出问题,比如
"d" === "d"; // true
let price = 123.123;
let price1 = "dddd@ddddd";
// 这里会解析为 'd+.d+'
let reg = new RegExp("d+.d+");
reg.test(price); // false
reg.test(price1); // true
// 此时需要再加一个斜杠
let reg = new RegExp("\\d+\\.\\d+");