Javascript中正则表达式中的问号(奇怪的行为)

时间:2010-06-23 02:03:02

标签: javascript regex

<html><body><script>
var matches = /(\w+)(\s*(\w+))?/.exec("aaa");
alert(matches.length);
alert(typeof(matches[3]));
</script></body><html>

我是正则表达式的新手,所以这可能是一个非常简单的问题。

/(\w+)(\s*(\w+))?/上方的正则表达式匹配“aaa”,“123”,“my_var”或“aaa bbb”,“123 456”,“my_var my_value”等模式。

对于像“aaa bbb”这样的表达式,匹配= ["aaa bbb", "aaa", " bbb", "bbb"],但对于像“aaa”这样的表达式,匹配= ["aaa", "aaa", ???, ???]

让我感到惊讶的第一件事是matches.length = 4.我原以为它是2,但我没有看到任何文件解释它应该是什么。它是如何工作的?

让我感到惊讶的第二件事是,我所测试的2个“额外”匹配在我测试过的2个浏览器中有所不同:

  • 在Firefox 3.6.3中,匹配[2]和匹配[3]未定义。

  • 在Internet Explorer 6中,匹配[2],匹配[3]为空字符串。

基本上,我应该如何检查我是否有“短”(如“aaa”)或“长”(如“aaa bbb”)表达?

3 个答案:

答案 0 :(得分:3)

matches数组包含两种匹配,整个匹配的字符串以及您的拥抱模式。因此,在这种情况下,它有四个元素,总匹配字符串"aaa",第一个子结果,"aaa"(\s*(\w+))(\w+)都有空匹配。< / p>

firefox和IE之间的区别是微不足道的。

如何检查匹配结果的答案很简单,只需检查matches[1]matches[3]的值,看看它们是未定义还是空。如果要解析的字符串都是\w+\s*\w+的模式,只需String.split()就可以了。如果您的字符串很短,结果数组将很短,如果您的字符串是"aaaa bbbb",结果数组将很长。但请注意"aaa "等案例。

答案 1 :(得分:3)

标准(ECMAScript 5)非常清楚。长度应为4,IE错误(令人震惊,我知道)。

从§15.10.2.1开始,“ NcapturingParens 是左侧捕获括号的总数。”你有3个。

State 是一个有序对( endIndex 捕获),其中 endIndex 是一个整数,< em> capture 是 NcapturingParens 值的内部数组。[...] 捕获的第n个元素是一个String,表示由第n组捕捉括号或未定义如果尚未达到第n组捕捉括号。“

§15.10.6.2,描述了exec,说:

  

9。 d。一世。让 r 成为[[Match]]调用的 State 结果。 [...]

     

12。让 n r 捕获数组的长度。 (这与15.10.2.1的 NCapturingParens 的值相同。)

     13。设A是一个新的数组,就像表达式new Array()[...]

一样      17。使用参数“length”,属性描述符{[[Value]]:I + 1}和true调用 A 的[[DefineOwnProperty]]内部方法。 [...]

     

20。对于每个整数 i ,使得 I&gt; 0 I≤n

     

一个。让 captureI 成为 r 捕获数组的 ith 元素。

     

湾使用参数ToString( i ),属性描述符{[[Value]]: captureI 调用 A 的[[DefineOwnProperty]]内部方法, [[Writable]:true,[[Enumerable]]:true,[[Configurable]]:true},true。

     

21。返回 A

因此长度应该是4(3 + 1),并且未达到的捕获(如模式中的(\s*(\w+)))仍未定义。幸运的是, undefined “”(空字符串)都是假的。这意味着当它们被视为布尔值时它们是错误的。因此,您可以通过if(matches[2])

解决IE的错误

答案 2 :(得分:2)

尝试使用这两个正则表达式:

var m1 = /(\w+)(\s*)/.exec("aaa");   // ["aaa", "aaa", ""]
var m2 = /(\w+)(\s+)?/.exec("aaa");  // ["aaa", "aaa", undef]

在第一种情况下,组#2不消耗任何字符,但*表示零长度匹配是可以的;据说该组没有匹配 - 即一个空字符串。在第二种情况下,(\s+)失败,但整体匹配成功,因为组本身是可选的。 undef结果表明该群组未参与比赛

这就是它应该如何工作:空字符串表示该组参与了比赛,但没有消耗任何字符; undef表示它没有参加比赛。通过为非参与组返回空字符串,Internet Explorer会删除不匹配的组和不匹配的组之间的区别。

但是,情况比这更糟糕,IE并不是唯一的坏人;有关血腥的详细信息,请参阅this blog post

但是有一件事是所有浏览器都同意的:match数组中的元素数量由正则表达式中的捕获组数量控制,无论它们是否参与匹配。