环视的四种类型
环视结构不匹配任何字符,只匹配文本中的特定位置。也称为零宽度断言。
| 类型 | 正则表达式 | 匹配成功的条件 | 匹配方向 |
|---|---|---|---|
| 肯定顺序环视 | (?=...) | 子表达式匹配右侧文本 | 从左到右 |
| 否定顺序环视 | (?!...) | 子表达式不能匹配右侧文本 | 从左到右 |
| 肯定逆序环视 | (?<=...) | 子表达式匹配左侧文本 | 从右到左 |
| 否定逆序环视 | (?<!...) | 子表达式不能匹配左侧文本 | 从右到左 |
以下是 Chrome(版本 99.0.4844.51)控制台的调试结果,其中否定逆序环视的支持还不完善。
let str = "77abc88";
str.replace(/(?=abc)/g, "#"); // '77#abc88'
str.replace(/(?!7)/, "#"); // '77#abc88'
str.replace(/(?<=abc)/g, "#"); // '77abc#88'
str.replace(/(?<!7)/, "#"); // '#77abc88'
非捕获括号与捕获括号
let str = "abc abaa bb";
str.match(/(?:ab)+/g); // ['ab', 'ab']
str.replace(/(?:ab)+/g, "$1,"); // '$1,c $1,aa bb'
str.replace(/(ab)+/g, "$1,"); // 'ab,c ab,aa bb'
可以从例子看出,(?:ab)并没有捕获并赋值给$1,(ab)有捕获并赋值给$1。
实战
给数字字符串加入千分位分隔符,比如 123,456,0
let str = "1234560";
str.replace(/(\d)(?=(?:\d{3})+$)/g, "$1,");
解答过程如下:
- 非捕获括号匹配
连续的3个数字:(?:\d{3}) - 捕获括号匹配
连续3个数字前的单个数字:(\d)(?:\d{3}) - 加入环视:
(\d)(?=(?:\d{3})+$),其中+$的含义是,n 组连续 3 个数字结尾的字符串 - 替换:
$1,