首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当我告诉它不要贪婪的时候,为什么这个霸王龙表现得贪婪呢?

当我告诉它不要贪婪的时候,为什么这个霸王龙表现得贪婪呢?
EN

Stack Overflow用户
提问于 2016-03-08 11:30:49
回答 2查看 152关注 0票数 3

我试图将系统宏的以下EBNF文法编码为正则表达式(如下所示),但尽管我尽了最大的努力,它似乎还是在多个宏之间贪婪地匹配:它不会在关闭}}@时停止。

代码语言:javascript
复制
    Expand ``@{{...}}@`` references which may appear in Step parameters.
    The syntax is described by the following EBNF grammar::

        depdata = "@{{", source identifier, ":", attribute, "}}@"
                | "@{{TAGS:", expression, "}}@" ;
        source identifier = ? printable 7-bit ASCII ? ;
        attribute = "DATADIR" | "TAGSFILE" | "RESULT_INT" ;
        expression = ? printable 7-bit ASCII ? ;

和我想出的Python正则表达式

代码语言:javascript
复制
@{{(?:(?:(?P<id>.*?):(?P<attr>DATADIR|TAGSFILE|RESULT_INT))|TAGS:(?P<expr>.+?))}}@

编辑:在expr组中添加缺失的+

Debuggex Demo

当在下面的测试用例中找到所有匹配时,我希望结果是三个匹配,但我只得到两个:

代码语言:javascript
复制
@{{TAGS:sTagsJob << "job||ID||source"}}@ test  @{{job:DATADIR}}@ email body @{{job:DATADIR}}@ blah

我期望的比赛是:

  1. 具有@{{TAGS:sTagsJob << "job||ID||source"}}@组集的expr
  2. 设置了@{{job:DATADIR}}@attr组的id
  3. @{{job:DATADIR}}@ (再次),设置了idattr

但与之相反的是:

  1. @{{TAGS:sTagsJob << "job||ID||source"}}@ test @{{job:DATADIR}}@
  2. @{{job:DATADIR}}@

为什么非贪婪的火柴(.+?)似乎是贪婪的?我错过了什么?

(是的,我知道EBNF语法很愚蠢,可以通过将固定字符串显示在右边来改进。但这不是我的问题:我想知道为什么我的regex-fu让我失望)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-03-08 12:03:10

点匹配任何字符(如果DOTALL模式关闭,则为换行符)。**?匹配0+字符,只是.*一次抓取所有内容,*?一步一步地完成,在重新尝试*?子subppatern之前检查匹配的后续子模式。在这里,您混淆了“贪婪”的含义:注意regex试图“以一切方式”找到匹配,当字符串中的某个位置发生不匹配时,它会重试量化的子模式,引擎会用贪婪的量词回溯,它会尽一切努力获取一个匹配。懒惰量词并不能保证您的模式不会因为量词定义中的额外?而过热。

因此,避免使用点匹配模式,如果您不是真正的意思,如果该模式是已知的。这里,可打印的ASCII模式是必需的-然后使用它,不依赖于点匹配。

代码语言:javascript
复制
@{{(?P<id>TAGS|[ -~]+?):(?:(?P<attr>DATADIR|TAGSFILE|RESULT_INT)|(?P<expr>[ -~]+?))}}@

regex演示

注意,[ -~]匹配任何可打印的ASCII字符。见http://www.catonmat.net/blog/my-favorite-regex/

模式匹配:

  • @{{前导定界符
  • (?P<id>TAGS|[ -~]+?) -匹配TAGS或1+可打印的ASCII字符的id组,但尽可能少,因为它也匹配: (您可以限制字符类的前瞻性以排除:或用[ -9;-~]替换以使模式更加优化,并使用这个量词消除? )
  • : -文字:
  • (?:(?P<attr>DATADIR|TAGSFILE|RESULT_INT)|(?P<expr>[ -~]+?)) --将DATADIRTAGSFILERESULT_INT匹配为attr组,或匹配一个或多个可打印的ASCII (尽可能少),并将位置匹配为组"expr“。同样,它在这里很懒,因为[ -~]}匹配。否则,您可以在这里使用脾气暴躁的象征(?:(?!}}@)[ -~])+。请参阅演示
  • }}@ -尾随分隔符
票数 3
EN

Stack Overflow用户

发布于 2016-03-08 11:40:36

这里有一个看起来像你想做的事的正则表达式:

代码语言:javascript
复制
@{{(?:(?:(?P<id>[^:]*?):(?P<attr>DATADIR|TAGSFILE|RESULT_INT))|TAGS:(?P<expr>.*?))}}@

这是正确匹配的:

代码语言:javascript
复制
MATCH 1
expr    [8-37]  `sTagsJob << "job||ID||source"`

MATCH 2
id  [50-53] `job`
attr    [54-61] `DATADIR`

MATCH 3
id  [79-82] `job`
attr    [83-90] `DATADIR`

您的正则表达式中有一个错误阻止它匹配TAG部件(P<expr>.?))}}@中忘记了一个kleene星?),但这本身并不能解决匹配过多的问题,所以我在<id>之后将这个点更改为“非冒号”。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35866192

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档