【问题标题】:How to make sense of these regex python replacements?如何理解这些正则表达式 python 替换?
【发布时间】:2022-01-22 05:08:39
【问题描述】:

我正在尝试替换正则表达式组的环境。我想用 LLL 和 MMM 替换 QQQQQ 和 SSSSS,中间的东西,前后保持不变。 (QQQQQ 和 SSSSS 可能会多次出现)。

在下面的代码中,(1) 似乎显示.*? 可以找到正确的字符串。

但在 (2) 中,使用(.*?) 作为一个组也能找到正确的字符串,但在替换中得到一个0

在 (3) 和 (4) 中,DOTALL 没有找到任何字符串。

我在这里使用正则表达式,但它与 re 相同。我也试过 $1 而不是 \1

代码如下:

doc1 = """AAA QQQQQ azertyuiop SSSSS BBB"""
doc2 = """
AAA
QQQQQ
azertyuiop
SSSSS
BBB
"""
# (1) OK - gives AAA LLL dd MMM BBB. .*? finds the right string
doc = regex.sub("QQQQQ.*?SSSSS", "LLL dd MMM", doc1)
print(doc)

# (2) gives AAA LLL ☺ MMM BBB - where does this ☺ come from?
doc = regex.sub("QQQQQ(.*?)SSSSS", "LLL \1 MMM", doc1)
print(doc)     

# (3) leaves string unchanged. Isn't DOTALL supposed to match line breaks?
doc = regex.sub("QQQQQ.*?SSSSS", "LLL dd MMM", doc2, regex.DOTALL)
print(doc)   

# (4) leaves string unchanged
doc = regex.sub("QQQQQ(.*?)SSSSS", "LLL \1 MMM", doc2, regex.DOTALL)
print (doc)   # leaves unchanged

(4) 是我正在尝试做的事情

【问题讨论】:

  • 对正则表达式使用原始字符串。否则\1 表示代码为1 的字符,而不是反向引用。
  • 原始字符串:这使得 (2) 工作。但是(3)和(4)仍然没有......
  • 您需要flags=regex.DOTALLregex.sub() 的第四个位置参数是 count,而不是 flags
  • @Barmar flags=regex.DOTALL 这就是答案。 @downvoters:提供的链接没有回答问题。如果您已经知道问题与原始字符串有关,那么它仅与问题的前半部分相关,并且如果您知道,那么您已经解决了问题。它没有提到 DOTALL。
  • 您问了多个问题。该链接解释了为什么 \1 在案例 2 中不起作用。

标签: python regex


【解决方案1】:

有两个问题。

  1. 您没有将re.DOTALL 作为正确的参数传递。如果您使用位置参数,flags 是第四个参数,但您将它作为第三个参数传递。使用flags= 关键字正确传递。
  2. 替换字符串中的\1 被解释为字符转义序列,而不是反向引用。这就是为什么你会在那里得到一个有趣的角色。使用原始字符串来防止转义序列处理。通常,您应该始终将原始字符串用于正则表达式和替换字符串,因为其中大量使用了反斜杠;见What exactly is a "raw string regex" and how can you use it?

这应该可行:

doc = regex.sub(r"QQQQQ(.*?)SSSSS", r"LLL \1 MMM", doc2, flags=regex.DOTALL)

【讨论】:

    猜你喜欢
    • 2014-10-02
    • 1970-01-01
    • 1970-01-01
    • 2012-06-17
    • 1970-01-01
    • 1970-01-01
    • 2018-10-17
    • 2011-02-12
    • 1970-01-01
    相关资源
    最近更新 更多