正则表达式前瞻与后顾
© 转载需要保留原始链接,未经明确许可,禁止商业使用。支持原创 CC BY-NC-SA 4.0
特别注意
Safari 版本低于 16.3 不支持零宽断言,谨慎使用!或使用替代方案
前瞻
exp(?=pattern) 匹配后面是 pattern 的 exp。
全称零宽正向先行断言。从匹配的位置 向右
看,匹配一些字符,但是并不包含匹配模式,只是确定是否匹配,也就是所谓的零宽。将其中的等号 =
替换为感叹号 ! 即为 零宽负正向先行断言。
后顾
(?<=pattern)exp 匹配前面是 pattern 的 exp。
全称零宽正向后行断言。从匹配的位置 向左 看,是否满足期望匹配规则。将其中的等号 = 替换为感叹号 ! 即为
零宽负正向后行断言。
示例
const str = 'netlify internet';
str.match(/net(?=lify)/);
// ['net', index: 0, input: 'netlify internet', groups: undefined];
str.match(/net(?!lify)/);
// ['net', index: 13, input: 'netlify internet', groups: undefined];
str.match(/(?<=inter)net/);
// ['net', index: 13, input: 'netlify internet', groups: undefined]
str.match(/(?<!inter)net/);
// ['net', index: 0, input: 'netlify internet', groups: undefined]
替代方案
可以使用分组匹配,然后只获取我们期望的匹配组。
匹配 lify 前面的所有非空白字符
const str = 'netlify';
const res = str.match(/(\S*)lify/);
// Output: ['netlify', 'net', index: 0, input: 'netlify', groups: undefined]
const matched = res[1];
// Output: net
匹配所有 <h2> 和 </h2> 中间的所有非空白字符,即解析 html 中的二级标题。global 匹配,注意 matchAll 返回的是迭代器 Iterator。
const html = `
<h2>First</h2>
<h2>Second</h2>
`;
const res = html.matchAll(/<h2>(\S*)<\/h2>/g);
// Output: RegExpStringIterator {}
console.log([...res]);
// Output: [
// ['<h2>First</h2>', 'First', index: 3, input: '\n <h2>First</h2>\n <h2>Second</h2>\n ', groups: undefined]
// ['<h2>Second</h2>', 'Second', index: 20, input: '\n <h2>First</h2>\n <h2>Second</h2>\n ', groups: undefined]
// ];
// 注意: Iterator 只能被迭代一次,此处为示例
const titles = [...res].map((r) => r[1]);
// Output: ['First', 'Second']
注意
迭代器只能被迭代一次。如上示例,执行 console.log([...res]) 之后,后面再迭代 [..res] 已经没有可迭代的数据了。