我有一个字符串,我想在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")
那为什么会发生这种情况以及如何解决呢?
答案 0 :(得分:4)
您在这里有两个问题。
首先,原始字符串文字的全部要点是它们不将反斜杠转义视为反斜杠转义。因此,ur"[\u2122\u00ae]"
实际上是字符[
,\
,u
,2
,1
等。
在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字符。同样,您可以 在源代码中使用它们,但必须以交互方式进行以下操作:
我不确定\u0099
是否真的比"a™b®c".decode('cp1252')
转义符好,但是它会起作用。
答案 1 :(得分:0)
只需删除字符串前的r
即可:
re.sub(u"[\u2122\u00ae]", "", u"a™b®c")