# 正则表达式 RegExp
# 正则表达式的规则
# 词元
词元,用来表示字符
元字符 | 匹配规则 | |
---|---|---|
\d | 数字 | 相当于 [0-9] |
\D | 非数字 | 相当于 [^\d] [^0-9] |
\w | 字母数字下划线 | 相当于[a-zA-Z0-9_] |
\W | 非字母数字下划线 | 相当于[^\w] [^a-zA-Z0-9_] |
\s | 空格字符 | 相当于[\n\t\r\v\f] |
\S | 非空格的其他字符 | 相当于[^\s] [^\n\t\r\v\f] |
. | 任意,匹配任意的单个字符,回车、换行除外 | |
\ | 转义,匹配这些字符需要用转义来表示 | \^ \. \[ \$ \( \) \\ |
# 数量
量词符 | 匹配规则 | 等价 |
---|---|---|
{n} | 表示恰好重复n 次 | |
{n,} | 示至少重复n 次 | |
{n,m} | 示重复不少于n 次,不多于m 次 | |
* | 重复 0 次以上 | 相当于{0,} |
+ | 至少一次 | 相当于{1,} |
? | 重复 0 次或 1 次 | 相当于{0, 1} |
# 逻辑
关系符 | 说明 | 举例 |
---|---|---|
分支结构,表示“或关系”(OR) | ||
- | 连接,/[A-Z]/ 表示匹配 26 个大写字母 | |
[] | 集合,字符集,匹配方括号内包含的任意字符 | /[xyz]/ 表示但凡出现 x, y, z 即可匹配 |
[^] | 取反,否定字符集,匹配不包含的任意字符 | /[^xyz]/ 表示除了x 、y 、z 之外都可以匹配 |
(xyz) | 组合,字符组,按照确切的顺序匹配字符,相当于匹配一个子串 |
# 边界
位置符 | 说明 | 举例 |
---|---|---|
^ | ^ 匹配字符串的开始位置 | |
$ | $ 匹配字符串的结束位置 |
# 断言
# 正向先行断言(?=pattern)
代表字符串中的一个位置,紧接该位置之后的字符序列能够匹配 pattern。
"The fat cat sat on the mat."
.match(/(T|t)he(?=\sfat)/)(
// ['The', 'T', index: 0, input: 'The fat cat sat on the mat.'
// 匹配`The`或者`the`,后面必须带有`\sfat`,因此第一个 The 会被匹配
"happynewyear2022goodluck"
)
.match(/.*(?=2022)/);
// ['happynewyear', index: 0, input: 'happynewyear2022', groups: undefined]
// 匹配2022前面的所有内容
# 正向后行断言(?<=pattern)
代表字符串中的一个位置,紧接该位置之前的字符序列能够匹配 pattern。
"The fat cat sat on the mat."
.match(/(?<=(T|t)he\s)(fat|mat)/)(
// ['fat', 'T', 'fat', index: 4, input: 'The fat cat sat on the mat.', groups: undefined]
// 匹配前面带有`The `或者`the `的 fat 或者 mat,因此第一个fat会被匹配
"happynewyear2022goodluck"
)
.match(/(?<=2022).*/);
// ['goodluck', index: 16, input: 'happynewyear2022goodluck', groups: undefined]
// 匹配2022后面的所有内容
# 负向先行断言?!pattern
同理,代表字符串中的一个位置,紧接该位置之后的字符序列不能匹配 pattern。
"The fat cat sat on the mat.".match(/(T|t)he(?!\sfat)/);
// ['the', 't', index: 19, input: 'The fat cat sat on the mat.', groups: undefined]
// 匹配`Th`或者 `the`,后面不能带有`\sfat`,因此第二个 the 会被匹配
# 负向后行断言(?<!pattern)
代表字符串中的一个位置,紧接该位置之前的字符序列不能匹配 pattern。
"The fat cat sat on the mat.".match(/(?<!(T|t)he\s)(cat|mat)/);
// ['cat', undefined, 'cat', index: 8, input: 'The fat cat sat on the mat.', groups: undefined]
// 匹配前面没有`The`或者`the`的 cat 或者mat因此 匹配到了cat
# 标记
标记 | 描述 |
---|---|
i | 不区分大小写 ignore |
g | 全局搜索 global |
m | 多行匹配 |
/.at(\.)?$/gm => The fat
cat sat
on the mat.
匹配到了每一行最后的任意字符加at
加点或者不加点 fat
sat
mat.
# 正则表达式实践
# 匹配中文(连接)
2020 的今天,[\u4e00-\u9fa5]还能匹配到所有中文吗? https://juejin.cn/post/6844904116842430471 (opens new window)
let reg1 = /[\u4e00-\u9fa5]/gm; // ×
let reg2 = /[\u4e00-\u9fd5]/gm; // ×
let reg2 = /[\u4e00-\u9fff]/gm; // √
console.log("\u4e00"); // '一' '一'
console.log("\u95a5"); // '龥' '閥'
console.log("\u9fd5"); // '龥' '龥'
结论: 使用 /[\u4e00-\u9fff]/
# 匹配前后空白(开头结尾)
let reg1 = /(^\s*)|(\s*$)/g;
# 匹配常规字符(元字符)
// 只能输入字母数字下划线
let reg1 = /^\w+$/;
// 只能输入数字
let reg2 = /^\d+$/;
// 匹配小写字母
let reg3 = /[A-Z]/;
// 匹配紧跟这小写字母的大写字母
let reg4 = /(?<=[a-z])([A-Z])/g;
# 匹配代码写法(断言)
// 小驼峰转下划线
let reg1 = /(?<=[a-z])([A-Z])/g;
let str1 = "openSettingDialog";
let str2 = str1.replace(reg1, (match) => {
return "_" + match.toLowerCase();
});
console.log(str2);
// 'open_setting_dialog'
// 同理
// 下划线转小驼峰
let reg2 = /(?<=\w+)(_[a-z])(?=\w+)/g;
let str3 = "open_setting_dialog";
let str4 = str3.replace(reg2, (match) => {
return match.replace("_", "").toUpperCase();
});
console.log(str4);
// 'openSettingDialog'
# 匹配标签(断言)
// 匹配a标签中的href
let reg1 = /(?<=<a.*href=")(.+)(?=")/g;
# 匹配数字位置
// 将123456789转化为123,456,789
let reg = /(?!^)(?=(\d{3})+$)/g;
let str = "123456789";
let str2 = str.replace(reg, ",");
console.log(str2);
// 将手机号18379836654转化为183-7983-6654
// 匹配位置 转换
let reg = /(?=(\d{4})+$)/g;
let str = "18379836654";
let str2 = str.replace(reg, "-");
console.log(str2);