【问题标题】:regex sub ignores end of string character正则表达式子忽略字符串字符的结尾
【发布时间】:2021-04-09 04:12:32
【问题描述】:

为什么这个python代码打印|ab||而不是|ab|d\nefgh|?我试图在c 之后捕获字符串的其余部分(包括多行),但我不知道我错过了什么。

import re

s = re.sub(
    "^(.*){1}c(.*){2}$",
    "|\\1|\\2|",
    """abcd
    efgh""",
    flags=re.DOTALL,
    count=1
)
print(s)

【问题讨论】:

  • 为什么要使用方括号 {1}{2}(通常用于明确指出 它们之前的字符/组的重复次数,而不是编号捕获组)?在这种情况下,它们似乎是不必要的。
  • 进一步扩展,我认为您误解了该结构。我打赌你认为这两个副短语是#1 和#2,但这是不对的。 {1} 表示“执行前一个令牌 1 次”,{2} 表示“执行前一个令牌 2 次”。
  • @TimRoberts 是的,我就是这么想的。现在我的代码没有按预期工作是有道理的。

标签: python python-3.x regex


【解决方案1】:

您获得该输出的原因是 {2} 重复了一个捕获组,为您提供了最后一次迭代的值。

第一次迭代有你想要的部分,但再次重复,组值将为空,因为.* 可以匹配 0+ 个字符。


使用(.*)c 将匹配直到最后一次出现 c。如果您想匹配直到第一次出现c,您也可以使用否定字符类。

如果您使用原始字符串表示法r"\1",则不需要双反斜杠

^([^c]*)c(.*)

Regex demo

import re

s = re.sub(
    "^([^c]*)c(.*)",
    r"|\1|\2|",
    """abcd
    efgh""",
    flags=re.DOTALL,
    count=1
)
print(s)

输出

|ab|d
    efgh|

【讨论】:

    【解决方案2】:

    这里似乎不需要{1}{2}。只需删除它们,它似乎就可以按您的预期工作。

    ^(.*)c(.*)
    
    re.sub(
        "^(.*)c(.*)",
        "|\\1|\\2|",
        """abcd
        efgh""",
        flags=re.DOTALL,
    )
    '|ab|d\n    efgh|'
    

    【讨论】:

      猜你喜欢
      • 2021-05-06
      • 1970-01-01
      • 1970-01-01
      • 2018-05-14
      • 2013-10-27
      • 2011-07-14
      • 1970-01-01
      • 1970-01-01
      • 2017-04-13
      相关资源
      最近更新 更多