Python 正则表达式否定元字符

4 投票
1 回答
1902 浏览
提问于 2025-04-17 07:02

Python中的元字符否定。

我在网上查了很多资料,试了几种不同的写法,现在想不出其他办法了。

我想给一些文件重命名。这些文件的标题里有年份,比如说[2002]。但有些文件没有方括号,我想把它们都加上。

所以我想找一个正则表达式(最好能编译的),在我脑海中,它看起来像(^[\d4^]),因为我想找到一组没有方括号的四个数字。我用方括号是希望能把它们绑定在一起,这样我就可以用类似[\1]的方式来重命名。

1 个回答

9

如果你想检查某个模式周围的内容,可以使用 前瞻后顾 断言。这些并不是匹配的一部分,而是告诉你期望在匹配的内容周围找到什么(或者不找到什么)。

因为我们不想要括号,所以需要使用 负向 后顾和前瞻。

负向前瞻的写法是 (?!...),它的意思是如果 ... 后面没有出现,就会匹配。负向后顾的写法是 (?<!...),它的意思是如果 ... 前面没有出现,就会匹配。

我们的例子稍微复杂一点,因为我们使用了 [],这两个符号在正则表达式中有特殊含义,所以我们需要用 \ 来转义它们。

所以我们可以这样构建一个模式:

  • [ 的负向后顾 - (?<!\[)
  • 四个数字 - \d{4}
  • ] 的负向前瞻 - (?!\])

这给我们带来了以下的 Python 代码:

>>> import re
>>> r = re.compile("(?<!\[)\d{4}(?!\])")
>>> r.match(" 2011 ")
>>> r.search(" 2011 ")
<_sre.SRE_Match object at 0x10884de00>
>>> r.search("[2011]")

要重命名,你可以使用 这个 re.sub 函数,或者在你编译的模式上使用 sub 函数。为了让它正常工作,你需要在年份周围加一对额外的括号,把它标记为一个组。

另外,在指定替换内容时,你需要用 \1 来引用这个组,所以你必须转义 \,或者使用原始字符串。

>>> r = re.compile("(?<!\[)(\d{4})(?!\])")
>>> name = "2011 - This Year"
>>> r.sub(r"[\1]",name)
'[2011] - This Year'

撰写回答