我解决了一个与 IE9 相关的正则表达式问题,但我不确定它是如何工作的或为什么会工作

I solved a regexp issue associated with IE9, but I'm not sure how or why it works

背景

我最近遇到一个问题,正则表达式在 IE9 中无法正常工作。我将问题追踪到表达式中的特定块,即 [^].

var reg = /((?:abc.[^]*?)?test\s*(?:xyz)?\s*)[^]*?/;

问题

var str = 'abc 123\nabc 123\nabc 123\ntest xyz';
var reg = /((?:abc.[^]*?)?test\s*(?:xyz)?\s*)[^]*?/;
alert(reg.exec(str));

换句话说:

输入:

abc 123
abc 123
abc 123
test xyz

输出

Expected: ["abc 123\nabc 123\nabc 123\ntest xyz","abc 123\nabc 123\nabc 123\ntest xyz"]

Chrome: ["abc 123\nabc 123\nabc 123\ntest xyz","abc 123\nabc 123\nabc 123\ntest xyz"]

IE9: ["test xyz", "test xyz"] // Wrong!!!

尝试的解决方案

我发现 [^] 块导致了错误。通过简单地将 [^] 切换为 [\S\s] 我能够在 IE9 中获得预期的输出。

var str = 'abc 123\nabc 123\nabc 123\ntest xyz';
var reg = /((?:abc.[\S\s]*?)?test\s*(?:xyz)?\s*)[\S\s]*?/;
alert(reg.exec(str));

输出

Expected: ["abc 123\nabc 123\nabc 123\ntest xyz","abc 123\nabc 123\nabc 123\ntest xyz"]

Chrome: ["abc 123\nabc 123\nabc 123\ntest xyz","abc 123\nabc 123\nabc 123\ntest xyz"]

IE9: ["abc 123\nabc 123\nabc 123\ntest xyz","abc 123\nabc 123\nabc 123\ntest xyz"]

问题

那么[^]和[\S\s]的本质区别是什么?这里有什么问题?我只是在处理 IE-javascript 引擎中的边缘情况吗?

[^][\s\S]没有区别。 [^] 存在于 Javascript 规范中,但 IE9 没有像其他许多 Javascript 功能那样处理它。

似乎 [^] 是 Javascript 特有的 AFAIK。我从未在其他正则表达式风格中见过它。在其他风格中,[^] 可以被视为语法错误或未闭合的字符 class(在这种情况下,右括号不是字符 class 的结尾,因为它紧跟在字符 class 之后^ 和 class 最终将在下一个右括号(如果存在)处结束)。

请注意,[^][] 是允许的,因为第一次将正则表达式功能添加到语言中(ECMA-262, 3rd edition 1999 年 12 月)。

在ECMA-262第三版规范(15.10.2.13)中,你可以看到负数字符class是这样定义的:

CharacterClass :: [^ ClassRanges ]

其中 ClassRanges 可以为空,也可以不为空。

此定义在 6th edition(2015 年 6 月)中始终相同。