【问题标题】:Writing unicode regex for both Python2 and Python3为 Python2 和 Python3 编写 unicode 正则表达式
【发布时间】:2017-04-12 03:08:03
【问题描述】:

我可以在 Python2 中使用 ur'something' 和 re.U 标志来编译正则表达式模式,例如:

$ python2
Python 2.7.13 (default, Dec 18 2016, 07:03:39) 
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> pattern = re.compile(ur'(«)', re.U)
>>> s = u'«abc «def«'
>>> re.sub(pattern, r' \1 ', s)
u' \xab abc  \xab def \xab '
>>> print re.sub(pattern, r' \1 ', s)
 « abc  « def « 

在 Python3 中,我可以避免 u'something' 甚至 re.U 标志:

$ python3
Python 3.5.2 (default, Oct 11 2016, 04:59:56) 
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> pattern = re.compile(r'(«)')
>>> s = u'«abc «def«'
>>> print( re.sub(pattern, r' \1 ', s))
 « abc  « def « 

但目标是编写正则表达式,使其同时支持 Python2 和 Python3。而在 Python3 中做ur'something' 会导致语法错误:

>>> pattern = re.compile(ur'(«)', re.U)
  File "<stdin>", line 1
    pattern = re.compile(ur'(«)', re.U)
                               ^
SyntaxError: invalid syntax

由于这是一个语法错误,即使在声明模式之前检查版本在 Python3 中也不起作用:

>>> import sys
>>> _pattern = r'(«)' if sys.version_info[0] == 3 else ur'(«)'
  File "<stdin>", line 1
    _pattern = r'(«)' if sys.version_info[0] == 3 else ur'(«)'
                                                             ^
SyntaxError: invalid syntax

如何对正则表达式进行 unicode 以同时支持 Python2 和 Python3?


虽然r' ' 可以很容易地被u' ' 替换,在这种情况下通过删除文字字符串。

为了理智起见,有些复杂的正则表达式需要r' ',例如

re.sub(re.compile(r'([^\.])(\.)([\]\)}>"\'»]*)\s*$', re.U), r'\1 \2\3 ', s)

所以解决方案应该包括文字字符串r' ' 用法,除非有其他方法可以绕过它。但请注意,使用字符串文字或unicode_literals 或来自__future__ 是不受欢迎的,因为它会导致大量其他问题,尤其是。在我使用的代码库的其他部分,请参阅http://python-future.org/unicode_literals.html

代码库不鼓励 unicode_literals 导入但使用 r' ' 表示法的特定原因是因为填充它并对它们中的每一个进行更改将非常痛苦,例如

【问题讨论】:

  • 也许我遗漏了一些东西,但对于这种情况,您似乎实际上并不 需要 原始字符串... IOW,u'(«)' 应该可以正常工作...
  • 啊哈,看到更新的问题。
  • re.escape 可以替换原始字符串用法吗? re.compile(re.escape(u'([^\.])(\.)([\]\)}&gt;"\'»]*)\s*$'), re.U) 之类的东西?
  • 我认为re.escape 不能真正帮助您。可惜他们不支持ur 前缀,但我猜他们想限制前缀的数量,毕竟Python 2 不必永远支持。 – 你为什么不在模块的基础上使用未来的unicode_literals,例如。仅适用于那些实际上包含大量复杂正则表达式的文件?对于其余部分,您似乎必须将反斜杠加倍...
  • nltk.tokenize.__init__ 有 6 个字符串文字(所有正则表达式模式),其中三个已经是 unicode。留下三个字符串进行测试。 (unicode_literals 不会影响导入的任何内容。)

标签: python regex python-2.7 python-3.x unicode


【解决方案1】:

你真的需要原始字符串吗?对于您的示例,需要 unicode 字符串,但不需要原始字符串。原始字符串很方便,但不是必需的 - 只需将您将在原始字符串中使用的任何 \ 加倍并使用纯 unicode。

Python 2 允许将原始字符串与 unicode 字符串连接(生成 unicode 字符串),因此您可以使用 r'([^\.])(\.)([\]\)}&gt;"\'' u'»' r']*)\s*$'
在 Python 3 中,它们都是 unicode,所以也可以。

【讨论】:

    猜你喜欢
    • 2021-10-01
    • 2013-07-26
    • 2010-09-06
    • 1970-01-01
    • 2012-05-15
    • 2017-01-23
    • 2016-04-22
    • 2017-01-10
    相关资源
    最近更新 更多