正则表达式反向断言
ECMAScript 9 引入了正则表达式的反向断言(Lookbehind Assertions),弥补了之前仅支持正向断言的不足。反向断言分为正向反向断言(Positive Lookbehind)和负向反向断言(Negative Lookbehind),用于匹配符合或不符合特定模式的字符串,但不会消耗字符。
反向断言的基本概念
反向断言允许在匹配字符串时检查当前位置之前的内容是否符合特定模式。正向反向断言使用 (?<=...)
语法,表示匹配前面必须符合 ...
模式的位置;负向反向断言使用 (?<!...)
语法,表示匹配前面不能符合 ...
模式的位置。
// 正向反向断言示例
const positiveLookbehind = /(?<=\$)\d+/;
console.log(positiveLookbehind.exec('$100')); // ["100", index: 1, ...]
// 负向反向断言示例
const negativeLookbehind = /(?<!\$)\d+/;
console.log(negativeLookbehind.exec('€100')); // ["100", index: 1, ...]
正向反向断言的用法
正向反向断言用于匹配前面必须符合特定模式的字符串。例如,匹配货币符号后的数字:
const pricePattern = /(?<=\$|€|¥)\d+(\.\d{2})?/g;
const text = 'Prices: $100, €200, ¥300.50';
console.log(text.match(pricePattern)); // ["100", "200", "300.50"]
另一个例子是匹配特定单词后的内容:
const afterHello = /(?<=Hello, )\w+/;
console.log(afterHello.exec('Hello, world')); // ["world", index: 7, ...]
负向反向断言的用法
负向反向断言用于匹配前面不能符合特定模式的字符串。例如,匹配前面不是货币符号的数字:
const noCurrencyPattern = /(?<!\$|€|¥)\b\d+\b/g;
const text = '100 $200 300 €400 500';
console.log(text.match(noCurrencyPattern)); // ["100", "300", "500"]
另一个例子是匹配不在引号内的单词:
const notInQuotes = /(?<!["'])\b\w+\b(?!["'])/g;
const text = 'word "quoted" not_quoted';
console.log(text.match(notInQuotes)); // ["word", "not_quoted"]
反向断言与捕获组的结合
反向断言可以与捕获组结合使用,实现更复杂的匹配逻辑。例如,提取特定前缀后的数字:
const prefixNumber = /(?<=ID: )(\d+)/;
const text = 'ID: 12345';
const match = prefixNumber.exec(text);
console.log(match[1]); // "12345"
另一个例子是匹配不在HTML标签内的特定单词:
const notInTag = /(?<!<[^>]*)\bimportant\b(?!>[^<]*>)/g;
const html = '<div>important</div> not important';
console.log(html.match(notInTag)); // ["important"] (只匹配第二个)
反向断言的性能考虑
反向断言在某些情况下可能影响正则表达式的性能,尤其是在处理长字符串时。因为引擎需要回溯检查前面的内容。例如:
// 可能较慢的反向断言
const slowPattern = /(?<=\b\w{10,})\d+/;
const longText = 'abcdefghij1234567890';
console.log(slowPattern.test(longText)); // true
浏览器兼容性与转义
ECMAScript 9的反向断言在现代浏览器中得到支持,但在旧环境中需要转译。使用Babel等工具可以确保兼容性:
// Babel配置示例
{
"plugins": ["@babel/plugin-transform-named-capturing-groups-regex"]
}
实际应用场景
反向断言在表单验证、日志分析和文本处理中非常有用。例如,验证密码不包含用户名:
const username = 'admin';
const passwordPattern = new RegExp(`(?<!${username}).{8,}`);
console.log(passwordPattern.test('secure123')); // true
console.log(passwordPattern.test('admin123')); // false
另一个例子是从日志中提取特定时间后的错误信息:
const errorAfterTime = /(?<=15:30:00\s).*ERROR.*/g;
const logs = `
15:29:59 INFO System started
15:30:01 ERROR Disk full
15:30:02 WARNING Memory low
`;
console.log(logs.match(errorAfterTime)); // ["ERROR Disk full"]
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益,请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:正则表达式命名捕获组
下一篇:正则表达式dotAll模式