我解决了一个与 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 月)中始终相同。
背景
我最近遇到一个问题,正则表达式在 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 月)中始终相同。