为什么python2的re模块无法识别u'®'字符

时间:2018-07-29 03:01:26

标签: python regex windows python-2.7 python-unicode

我有一个字符串,我想在Python2中re.sub使用此字符串,所以我尝试了以下语句,它起作用了

>>> import re
>>> re.sub(u"[™®]", "", u"a™b®c")
'abc'

但是,当我尝试以下语句时,它在两个Windows 10上都失败了(Python 2.7.15 | Anaconda,Inc. |(默认,2018年5月1日,18:37:09)[MSC v.1500 64位( AMD32))。

>>> re.sub(ur"[\u2122\u00ae]", "", u"a™b®c")
u'a?b?c'

我已经尝试了Python and regular expression with Unicode中的解决方案,但是它也不起作用。

>>> myre = re.compile(ur'[\u2122\u00ae]', re.UNICODE)
>>> print myre.sub('', u"a™b®c")

那为什么会发生这种情况以及如何解决呢?

2 个答案:

答案 0 :(得分:4)

您在这里有两个问题。


首先,原始字符串文字的全部要点是它们不将反斜杠转义视为反斜杠转义。因此,ur"[\u2122\u00ae]"实际上是字符[\u21等。

在Python 3中,这很好,因为re模块将\u理解为表示Unicode字符的转义符,因此该模式最终成为带有U+2122和{{1}的字符类},完全符合您的需求。但是在Python 2中却不是,所以字符类最终变成一堆无用的垃圾。

如果将其更改为使用非原始字符串文字,则可以解决该问题:U+00AE。当然,这将带来所有其他潜在的问题,使人们想首先使用正则表达式使用原始字符串文字,但是幸运的是,这里没有任何这些文字。


第二个问题是您在Unicode文字中使用Unicode字符而没有编码声明。同样,在Python 3中不是问题,但在Python 2中是问题。

键入u"[\u2122\u00ae]"时,很有可能您实际上给的不是Python的"a™b®c"字符,而是\u2122字符。您的控制台可能位于类似cp1252的位置,因此当您键入或粘贴\u0099时,它实际上给的Python是U + 0099,而不是U + 2122。当然,您的控制台也会错误地显示 内容,因此最终看起来像U+0099。但是Python不知道发生了什么。只是看到U + 0099与U + 2122是不同的字符,因此没有匹配项。 (您的第一个示例之所以有效,是因为您的搜索字符串也是包含错误的,因此恰好匹配。)

在源代码中,您可以通过以下方式解决此问题:添加编码声明以告知Python您正在使用cp1252,或者通过告诉编辑器首先使用UTF-8而不是cp1252。但是在交互式解释器中,您可以获得控制台所需的任何编码,并且无处可放置编码声明。

真的,对此没有好的解决方案。

好吧,有:升级到Python3。首先存在它的主要原因是让Unicode这样的头痛问题消失了,而Python 2的生命周期还不到一年半。您真的想了解当今如何在Python 2中处理Unicode的烦恼吗?

您还可以获得一个UTF-8终端(Python也可以识别这种终端)。这在macOS或最新的Linux发行版上是自动的;在Windows上,要困难得多,而且可能不是您想去这里的方式。

因此,唯一的选择是永远不要在交互式解释器的Unicode文字中使用Unicode字符。同样,您可以 在源代码中使用它们,但必须以交互方式进行以下操作:

  • 使用反斜杠转义符。
  • 使用非Unicode文字并在各处仔细解码。

我不确定\u0099是否真的比"a™b®c".decode('cp1252')转义符好,但是它会起作用。

答案 1 :(得分:0)

只需删除字符串前的r即可:

re.sub(u"[\u2122\u00ae]", "", u"a™b®c")