为什么
/<.+?> e/.exec("a <b> c <d> e")
(意外)返回
["<b> c <d> e"]
代替
["<d> e"]
非贪婪的运营商似乎什么都不做......
为什么
/<.+?> e/.exec("a <b> c <d> e")
(意外)返回
["<b> c <d> e"]
代替
["<d> e"]
非贪婪的运营商似乎什么都不做......
"<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"]
使它变得非贪婪,您正在经历的?行为正在发生,因为您没有告诉它结束尝试匹配>不属于> e. 目前;
/<.+?> e/
<>或行尾
null>
> e,则完全匹配2 请记住,.+将愉快地匹配>、 空格和字母,所以这些被包括在内。看起来你想要
/<[^>]+?> e/
<>>或找到行尾
null>
> e,则完全匹配1导致
/<[^>]+?> e/.exec("a <b> c <d> e")
// ["<d> e"]
发生这种情况是因为当它遇到>不属于 的a 时> e,它知道它的起始位置一定是错误的,所以再次沿着文本继续直到下一个<。
这可以让你理解惰性操作符的作用:
/<.+?> 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)。
来自正则表达式.info:
理解这一点非常重要:正则表达式导向的引擎将始终返回最左边的匹配,即使稍后可以找到“更好”的匹配。
正则表达式引擎从左边开始遍历字符串,并且对于每个字符,说“我可以从这里找到匹配吗?” 非贪婪运算符永远不会阻止在没有匹配项的情况下找到匹配项,因此引擎将继续尝试,这意味着当它从第一个开始检查时<,它会找到匹配项并立即返回(没有永远检查从 second 开始的匹配<,因为它没有那么远)。
为了匹配你想要的,一组尖括号后跟一个“e”,你只需确保>中间没有“
<[^>]+>[ ]e
(请注意,为了清楚起见,空格位于字符类中,而不是因为必须如此。)
通过变得.+懒惰,模式必须> 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/