句点导致Python中的多行正则替换停止?

1 投票
2 回答
1259 浏览
提问于 2025-04-17 12:48

我有一个包含多行的字符串,想要替换一些内容,但不知道为什么不成功。奇怪的是,字符串中的一个句号让正则表达式无法匹配。

我的字符串是:

s = """
[some_previous_text]
<start>
one_period .
<end>
[some_text_after]
"""

我想要的结果是:

s = """
[some_previous_text]
foo
[some_text_after]
"""

我最开始尝试的方式,但什么都没匹配到:

>>> import re
>>> s = "<start>\none_period .\n<end>"
>>> print re.sub("<start>[^.]*<end>", "foo", s)
<start>
one_period .
<end>

不过,当我把句号去掉后,它就能正常工作了:

>>> import re
>>> s = "<start>\nno_period\n<end>"
>>> print re.sub("<start>[^.]*<end>", "foo", s)
foo

而且,当我在句号前加了一个 <end> 标签时,它匹配到了第一个 <end> 标签:

>>> import re
>>> s = "<start>\n<end>\none_period .\n<end>"
>>> print re.sub("<start>[^.]*<end>", "foo", s)
foo
one_period .
<end>

那么这是怎么回事呢?为什么句号会让 [^.]* 无法匹配呢?

编辑:

已解决

我错误地认为插入符号 ^ 是用来匹配新行的。其实我需要的是一个 re.DOTALL 标志(正如 Amber 所说)。这是我现在使用的表达式:

>>> import re
>>> s = "<start>\none_period .\n<end>"
>>> print re.sub("<start>.*<end>", "foo", s, flags=re.DOTALL)
foo

2 个回答

1

这是因为 [^.]* 是一个否定字符类,它可以匹配任何字符,除了句点(.)。

你可能想要的是类似 <start>.*?<end> 的写法,再加上 re.S 这个修饰符,这样点号(.)就可以匹配换行符了。

re.sub("<start>.*?<end>", "foo", s, flags=re.S)
4

为什么不呢?[^.] 的意思是“所有不是 . 的字符”,所以它不会匹配句点。


也许你想用 .*(表示任意数量的任意字符)来代替 [^.]*

如果你想匹配跨越多行的内容,可以使用 re.DOTALL

re.sub("<start>.*<end>", "foo", s, flags=re.DOTALL)

撰写回答