Regex “为什么可以?”;a*a+&引用;及;(a{2,3})*a{2,3};匹配“;aaaa“;而";(a{2,3})*”;不能

Regex “为什么可以?”;a*a+&引用;及;(a{2,3})*a{2,3};匹配“;aaaa“;而";(a{2,3})*”;不能,regex,Regex,我对*的理解是,它消耗尽可能多的字符(贪婪地),但在必要时“回馈”。因此,在a*a+中,a*将给a+返回一个(或更多?)字符,以便匹配 但是,在(a{2,3})*中,为什么a{2,3}的第一个“实例”不给第二个“实例”一个字符,以便第二个“实例”可以匹配 此外,在(a{2,3})*a{2,3}中,第一部分似乎给了第二部分一个字符。主要问题是: 我对*的理解是,它消耗尽可能多的字符(贪婪),但在必要时“回馈” 这是完全错误的。这不是贪婪的意思 贪婪只是意味着“使用尽可能长的匹配”。它不给任何回报

我对
*
的理解是,它消耗尽可能多的字符(贪婪地),但在必要时“回馈”。因此,在
a*a+
中,
a*
将给
a+
返回一个(或更多?)字符,以便匹配

但是,在
(a{2,3})*
中,为什么
a{2,3}
的第一个“实例”不给第二个“实例”一个字符,以便第二个“实例”可以匹配


此外,在
(a{2,3})*a{2,3}
中,第一部分似乎给了第二部分一个字符。

主要问题是:

我对*的理解是,它消耗尽可能多的字符(贪婪),但在必要时“回馈”

这是完全错误的。这不是贪婪的意思

贪婪只是意味着“使用尽可能长的匹配”。它不给任何回报

一旦你用这种新的理解来解释这些表达,一切都是有意义的


  • a*a+
    -零个或多个
    a
    ,后跟一个或多个
    a

  • (a{2,3})*a{2,3}
    -两个或三个
    a
    中的零个或多个,后跟两个或三个
    a
    (注意:要记住的关键是“零个或多个”,不匹配任何字符的第一部分被视为匹配)

  • (a{2,3})*
    -两个或三个
    a
    中的零个或多个(这意味着在匹配三个
    a
    s后,最后一个
    a
    左不能匹配)


  • 解决问题的一个简单方法是将
    aaaa
    与regex
    ^(A{2,3})*$
    匹配

    你的问题是:

    (a{2,3})*
    的情况下,regex似乎没有消耗那么多 尽可能地表现个性

    我建议不要在回馈角色时思考。相反,关键是接受

    一旦regex接受您的字符串,匹配将结束。模式
    a{2,3}
    仅匹配
    aa
    aaa
    。因此,在将
    aaaa
    (a{2,3})*
    匹配的情况下,贪婪引擎将匹配
    aaa
    。然后,它不能匹配更多的
    a{2,3}
    ,因为只剩下一个
    a
    。尽管正则表达式引擎能够回溯并匹配额外的
    a{2,3}
    ,但它不能
    aaa
    现在被正则表达式接受,因此正则表达式引擎不会进行昂贵的回溯


    如果在正则表达式的末尾添加一个
    $
    ,它只会告诉正则表达式引擎部分匹配是不可接受的。此外,很容易解释接受和回溯的
    (a{2,3})*a{2,3}
    情况。

    回溯仅在匹配失败时进行,但是
    aaa
    是有效匹配,可以使用负前瞻
    (?!a)
    来防止匹配后出现
    a


    如果是这种情况,为什么
    a*a+
    aaaa
    匹配
    a*
    将消耗所有四个字符,留下
    a+
    零个字符。
    a*
    表示零个或多个a,因此它不能匹配任何内容,
    a
    aa
    aaa
    aaaa
    。这就是它起作用的原因。另一方面,
    (a{2,3})*
    表示匹配两个
    a
    或三个
    a
    中的零个或多个。因此,它只能不匹配、
    aa
    aaa
    。请注意,在这两种情况下,
    *
    都不会返回任何内容。不要用回馈的方式思考,而要用如果的方式思考/else@sqd这是回溯。@iBug:在这种情况下,技术上回溯是不必要的。因为我们不匹配捕获组,所以我们可以将regexp编译成简单的状态机。你说的“不能”是什么意思?它。这应该用你正在使用的任何正则表达式的味道来标记。它肯定匹配-检查这里:
    (aaa?)*
    
    (aaa?)*(?!a)