【问题标题】:Strange behavior of capturing group in regular expression正则表达式中捕获组的奇怪行为
【发布时间】:2016-02-20 00:03:17
【问题描述】:

给定以下简单的正则表达式,其目标是捕获引号字符之间的文本:

regexp = '"?(.+)"?'

当输入类似于:

"text"

捕获组(1)有以下内容:

text"

我希望 group(1) 只有text(不带引号)。有人可以解释发生了什么以及为什么正则表达式捕获" 符号,即使它在捕获组#1 之外。我不明白的另一个奇怪行为是为什么第二个引号字符被捕获但不是第一个,因为它们都是可选的。最后我使用以下正则表达式修复了它,但我想了解我做错了什么:

regexp = '"?([^"]+)"?'

【问题讨论】:

    标签: python regex


    【解决方案1】:

    Quantifiers in regular expressions are greedy:他们尝试匹配尽可能多的文本。因为你最后的" 是可选的(你在正则表达式中写了"?),所以.+ 将匹配它。

    使用[^"] 是一种可接受的解决方案。缺点是您的字符串不能包含 " 字符(这可能是可取的,也可能不是可取的,具体取决于具体情况)。

    另一个是使"成为必需的:

    regexp = '"(.+)"'
    

    另一种方法是使用+? 使+ 不贪婪。但是,您还需要添加锚点 ^$(或类似的,取决于上下文),否则它将仅匹配第一个字符(t"test" 的情况下):

    regexp = '^"?(.+?)"?$'
    

    此正则表达式允许" 字符位于字符串中间,这样"t"e"s"t" 将导致t"e"s"t 被组捕获。

    【讨论】:

    • 你说的正则表达式很贪心是什么意思。
    • @WiktorStribiżew:更新的答案。希望这很清楚
    【解决方案2】:

    为什么正则表达式即使在捕获组之外仍捕获 " 符号 #1

    "?(.+)"? 模式包含一个greedy dot matching 子模式。 . 也可以匹配 ""? 是一个 可选 子模式。这意味着如果前一个子模式是贪婪的(并且.+ 是一个贪婪的子模式)并且可以匹配后续子模式(并且. 可以匹配一个"),那么.+ 将接管该可选值。

    negated character class 是匹配除特定字符/范围之外的任何字符的正确方法。 [^"] 永远不会匹配 ",因此最后一个 " 永远不会与此模式匹配。

    为什么第二个引号字符被捕获但不是第一个,因为它们都是可选的

    第一个"? 出现在贪心点匹配模式之前。引擎看到"(如果它在字符串中)并将引号与第一个"? 匹配。

    【讨论】:

      【解决方案3】:

      .+ 是贪婪的。它会收集所有内容,包括“.your final”?不需要存在引号,因此 .+ 包含引号。

      第一个引号未被捕获,因为它与“?”匹配

      【讨论】:

        【解决方案4】:

        正则表达式默认是贪婪的,它会尽快尝试匹配。

        由于您的捕获组包含.+,这将匹配"? 之前的结束括号。然后,当退出组时,它位于您的行尾,由可选的" 匹配。

        【讨论】:

          【解决方案5】:

          .+ 可以匹配任何字符(包括")。当它到达输入末尾时,"? 匹配,因为这意味着 " 是可选的。

          你应该使用“非贪婪”:

          regex "(.+?)"

          【讨论】:

            猜你喜欢
            • 2012-03-02
            • 2018-06-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-09-17
            • 1970-01-01
            • 2013-07-13
            相关资源
            最近更新 更多