【问题标题】:Continuing at the end of the previous match in RegEx (PCRE)在 RegEx (PCRE) 中的上一场比赛结束时继续
【发布时间】:2011-06-02 03:26:03
【问题描述】:

我试图阻止 \G 锚匹配字符串的开头。我只希望它在最后一次正则表达式匹配结束时匹配。

给定以下文本:

Pig, Cow, Goat
fruit: apple, orange, peach, pear
vegetable: Carrot, Lettuce, Cellery

还有这个模式:

(fruit:|\G)([\w]+|[\, ])

我希望它只匹配“fruit:”之后的单词,但我需要它单独捕获每个单词。如果我只是在这个模式的最后加上一个 +,它会匹配“fruit:”之后的所有单词,但它只会捕获“pear”,因为 + 的每次迭代都会踩到最后一个。

这就是问题所在。此模式有效,除了它还匹配“Pig, Cow and Goat”,因为 \G 将匹配最后一个匹配的结尾或整个字符串的开头。如何防止它匹配整个字符串的开头?

我在 PHP 中使用 PCRE,并且一直在使用 Rubular.com 来帮助我进行快速测试。

【问题讨论】:

    标签: php regex pcre


    【解决方案1】:

    在我看来,你的正则表达式并没有给你你所说的你想要的。你说你想要“水果:”后面的每个单词。鉴于你的例子,我认为你的第一次尝试并没有真正给你。试试:

    (?:fruit:\s*|\G,\s*)(\w+)
    

    如果你匹配所有,那应该给你没有空格或标点符号的单词。

    这里有一个纲要:

    • (?: - 启动非捕获组
    • fruit:\s* - 一场好比赛的序言
    • | - 或
    • \G,\s*) - 最后匹配位置,逗号和零个或多个空格
    • (\w+) 捕获一个或多个单词字符

    编辑:

    为了防止您在第一行得到匹配的情况,如果第一行以逗号开头,后跟一个或多个逗号分隔的单词,只需在起始锚点上添加一个负零宽度后视即可在\G之前:​​

    (?:fruit:\s*|(?<!^)\G,\s*)(\w+)
    

    【讨论】:

    • 这对我有帮助的地方是您在\G 之后包含了分隔符,。有趣的想法。我的问题是分隔符和空格是可选的。由于它们是可选的,因此此模式可以轻松地从文档 Pig 的开头开始匹配,我无法控制。我也没有解释我正在使用preg_replace,我想单独匹配单词fruit:,这样我就可以使用替换字符串将它返回到它的位置。因此我没有在我的模式中使用?:
    • 只需在水果周围加上括号即可捕获它。关于分隔符和空格是可选的,那么,你会如何分隔单词呢?
    • 另一件事... \G 对我来说,至少我如何将它放在上面的模式中,似乎没有捕获一行的开头,除非它是第一行,第一行以逗号开头。您是否使用了一些您未提及的选项? “点匹配换行符”? “^$ 匹配换行符”?
    • 首先,您的建议很有帮助,我认为它解决了我的问题。回答您的 cmets:单词可以用逗号、正斜杠或反斜杠分隔,并且在标点符号之前和/或之后可能有一个空格。我正在解析从其他人创建的 PDF 转换的文本文件,所以我必须为各种东西做好准备。没错,\G 与文档的开头不匹配,除非它以逗号开头,我希望不会发生这种情况。所以我认为这对我有用。
    猜你喜欢
    • 2012-03-27
    • 2010-10-03
    • 2021-08-24
    • 2016-01-29
    • 2016-11-18
    • 1970-01-01
    • 2015-09-16
    • 2023-01-20
    • 1970-01-01
    相关资源
    最近更新 更多