为什么
/<.+?> e/.exec("a <b> c <d> e")
(意外地)返回
["<b> c <d> e"]
而不是
["<d> e"]
非贪婪的运营商似乎什么都不做......
答案 0 :(得分:3)
"<b> c <d> e"
是完全有效的结果。你的正则表达式&#34;匹配<
然后匹配> e
&#34; - 这正是你得到的。 &#34;直观&#34; "<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"]
答案 1 :(得分:3)
?
使其变得非贪婪,您正在经历的行为正在发生,因为您并没有告诉它在>
处结束尝试匹配> e
不属于{{{ 1}}。目前;
/<.+?> e/
<
>
或行尾
null
>
> e
,则完全匹配2
请记住,.+
会很乐意匹配>
,空格和字母,因此这些内容会被包含在内。看起来像你想要的
/<[^>]+?> e/
<
>
>
或找到了行尾
null
>
> e
,则完全匹配1
导致
/<[^>]+?> e/.exec("a <b> c <d> e")
// ["<d> e"]
这种情况发生的原因是当遇到不属于>
的{{1}}时,它知道它的起始位置一定是错误的,所以继续沿着文本继续直到下一个> e
答案 2 :(得分: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
表示:找到<
后,找到第一个 > e
<.+> e
表示:找到<
后,找到最后 > e
在您的具体情况下,您可以简单地使用<[^>]+> e
(这更快,因为它更快 - 当它可能时,总是更喜欢X[^X]X
符号而不是X.*?X
符号。 / p>
答案 3 :(得分:2)
这是一个非常重要的要点:一个正则表达式的引擎 将始终返回最左边的匹配,即使“更好”的匹配可以 可以在以后找到。
正则表达式引擎从左侧穿过字符串,对于每个字符,说“我能从这里找到匹配吗?”非贪婪的运算符永远不会阻止在没有匹配的情况下找到匹配,因此引擎将继续尝试,这意味着当它从第一个<
开始检查时,它将找到匹配并返回它立刻(没有检查从第二个<
开始的匹配,因为它没有那么远)。
为了匹配你想要的东西,一组尖括号后跟一个“e”,你只需要确保中间没有>
“
<[^>]+>[ ]e
(请注意,为了清晰起见,空格位于字符类中,而不是因为它需要。)
答案 4 :(得分:2)
通过使.+
延迟,模式必须在> e
的第一次之后找到匹配的<.+?
。既然如此,在你的情况下是子串<b> c
,模式的其余部分> 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/