5

为什么

/<.+?> e/.exec("a <b> c <d> e")

(意外)返回

["<b> c <d> e"]

代替

["<d> e"]

非贪婪的运营商似乎什么都不做......

4

5 回答 5

3

"<b> c <d> e"是一个完全有效的结果。你的正则表达式说“然后匹配<一些东西,然后> e” - 这正是你得到的。“直观地”"<d> e"可能看起来更好的匹配,但是,正则表达式引擎没有直觉,它只是找到第一个匹配的子字符串并停在那里。

当您在两场或多场比赛之间做出选择时,贪婪就会发挥作用 - 这里不是这种情况,因为只有一场比赛。如果您的字符串有两个> e,则会有所不同:

/<.+> e/.exec("a <b> c <d> e more > e")
> ["<b> c <d> e more > e"]
/<.+?> e/.exec("a <b> c <d> e more > e")
> ["<b> c <d> e"]
于 2013-08-21T12:23:52.993 回答
3

使它变得非贪婪,您正在经历的?行为正在发生,因为您没有告诉它结束尝试匹配>不属于> e. 目前;

/<.+?> e/
  1. 浏览文本直到<
  2. 匹配直到>或行尾
    1. 如果是行尾,则返回null
    2. 如果它是>
      1. 如果是> e,则完全匹配
      2. 否则,包括并恢复2

请记住,.+将愉快地匹配>、 空格和字母,所以这些被包括在内。看起来你想要

/<[^>]+?> e/
  1. 浏览文本直到<
  2. 匹配所有非>
  3. >或找到行尾
    1. 如果是行尾,则返回null
    2. 如果它是>
      1. 如果是> e,则完全匹配
      2. 否则,返回步骤1

导致

/<[^>]+?> e/.exec("a <b> c <d> e")
// ["<d> e"]

发生这种情况是因为当它遇到>不属于 的a 时> e,它知道它的起始位置一定是错误的,所以再次沿着文本继续直到下一个<

于 2013-08-21T12:25:15.983 回答
3

这可以让你理解惰性操作符的作用:

/<.+?> e/.exec("a <b> c <d> e <f> e")` // -> ["<b> c <d> e", "<f> e"]
/<.+> e/.exec("a <b> c <d> e <f> e")`  // -> ["<b> c <d> e <f> e"]

<.+?> e意思是:一旦<找到a,就找到第一个 > e

<.+> e意思是:一旦<找到a,找到最后一个 > e

在您的特定情况下,您可以简单地使用<[^>]+> e(这会更好,因为更快 - 如果可能,总是更喜欢X[^X]X符号而不是那个X.*?X)。

于 2013-08-21T12:27:24.463 回答
2

来自正则表达式.info

理解这一点非常重要:正则表达式导向的引擎将始终返回最左边的匹配,即使稍后可以找到“更好”的匹配。

正则表达式引擎从左边开始遍历字符串,并且对于每个字符,说“我可以从这里找到匹配吗?” 非贪婪运算符永远不会阻止在没有匹配项的情况下找到匹配项,因此引擎将继续尝试,这意味着当它从第一个开始检查时<,它会找到匹配项并立即返回(没有永远检查从 second 开始的匹配<,因为它没有那么远)。

为了匹配你想要的,一组尖括号后跟一个“e”,你只需确保>中间没有“

<[^>]+>[ ]e

(请注意,为了清楚起见,空格位于字符类中,而不是因为必须如此。)

于 2013-08-21T12:26:18.700 回答
2

通过变得.+懒惰,模式必须> e在第一次出现<.+?. 因为在你的情况下是 substring <b> c,其余的 pattern> e还不匹配,所以.+你的表达式部分继续进行,直到最后> e部分匹配......

'a <b> c <d> e'
 xx//<-- no matches
   <//<-- opening < matches, switch to .+?
    b//<-- matched by .+
     > c//<-- does not match > e, but does match .+
         <d// matched by .+
           > e// matches rest of expression (> e), the resulting match is:

   <b> c <d> e

在您的情况下,我不使用惰性运算符,而是简单地选择:

/(?:<)[^>]+> e/
//or even
/<[^>]+>\s+e/
于 2013-08-21T12:35:22.247 回答