JavaScript中的正则表达式,始终为‘;未定义’;如果需要,请使用带问号的分组

JavaScript中的正则表达式,始终为‘;未定义’;如果需要,请使用带问号的分组,javascript,regex,node.js,Javascript,Regex,Node.js,我试图做的是提取匹配模式,但其中一个模式可能是可选的。让我们直接来看一个例子 我想匹配的目标文本是 <foo>\n<bar>\n#####<foo>\n#####<bar> (我之所以使用?这里是因为特定的模式可以是可选的。例如,我不希望匹配完全失败,而不仅仅是此模式的“未定义”。) 我期望str.match()返回的结果是 为什么? 我在nodejs/chrome和IE中都试过,但都没有成功,这意味着这种行为在整个JS引擎中是一致的。但它的行为

我试图做的是提取匹配模式,但其中一个模式可能是可选的。让我们直接来看一个例子

我想匹配的目标文本是

<foo>\n<bar>\n#####<foo>\n#####<bar>
(我之所以使用?这里是因为特定的模式可以是可选的。例如,我不希望匹配完全失败,而不仅仅是此模式的“未定义”。)

我期望str.match()返回的结果是

为什么?

我在nodejs/chrome和IE中都试过,但都没有成功,这意味着这种行为在整个JS引擎中是一致的。但它的行为与我尝试过的许多工具中的一个不同。我不确定这是工具本身的问题还是不同的实现

var re = /(#{5})/;
console.log ("<foo>\n<bar>\n#####<foo>\n#####<bar>".match (re));
console.log ("<foo>\n<bar>\nfoo>\n<bar>".match (re));
另外,不要使用字符串#match(),它比RegExp#exec()慢,并且两者都返回相同的值:


我想,如果您将模式设置为完全可选,那么它将完全不匹配任何内容(即空字符串)。我不知道为什么在那之后它不继续匹配你的模式。Regex是贪婪的,所以它应该找到最长的匹配,这意味着它应该返回匹配的字符串,如果它是可选的。实际上,你是否尝试过使用
/g
使其全局化?也许这是相关的。@ChrisHayes似乎就是这样。如果使用/g,您会得到大量的
匹配项,并混合了一些
。因为它是可选的,所以它匹配每个字符之间的空字符串。如果没有/g,它将在测试字符串的开头匹配空字符串。这与其他风格(如java)不同。在这种情况下,没有可选模式会匹配任何内容,因为正则表达式引擎总是会返回null,而不仅仅是这种情况,对吗?是的,exec()和match()在不匹配时返回null。另外,不要使用match(),它比exec()慢。请看我的答案。@ChundongWang可选模式在与其他模式组合时非常有用,尤其是在其他模式之间。例如,如果要匹配“2012年11月14日”和“2012年11月14日”之类的日期,可以使用模式
/Nov(ember)?2012年11月14日/
。但可选模式本身将返回null,除非它与字符串开头的内容匹配。@Barmar,我同意可选模式需要与其他模式一起使用。我在这里发布的问题不是我在现实世界中使用的东西,而是为Stackoverflow而简化的。但它仍然是未定义的,即使我将它与实际案例中的其他模式相结合。让我们以您的模式为例/十一月(余烬)?2012年11月14日/将获得“2012年11月14日”的比赛,这是肯定的。但即使使用pattern/Nov(\n | ember),它也无法与“2012年11月14日”匹配?第14(th)?,2012/。
[ '#####',
  '#####',
  index: 12,
  input: '<foo>\n<bar>\n#####<foo>\n#####<bar>' ]
[ '',
  undefined,
  index: 0,
  input: '<foo>\n<bar>\n#####<foo>\n#####<bar>' ]
/(#{5})+/
var re = /(#{5})/;
console.log ("<foo>\n<bar>\n#####<foo>\n#####<bar>".match (re));
console.log ("<foo>\n<bar>\nfoo>\n<bar>".match (re));
[ '#####',
  '#####',
  index: 12,
  input: '<foo>\n<bar>\n#####<foo>\n#####<bar>' ]
null
> /a/.exec("a")
[ 'a', index: 0, input: 'a' ]
> /a/.exec("b")
null
> "a".match(/a/)
[ 'a', index: 0, input: 'a' ]
> "b".match(/a/)
null