如何指定一個 Unicode 字符的範圍?

28
如何指定一个Unicode字符范围从' '(空格)到\u00D7FF
我有一个正则表达式,类似于r'[\u0020-\u00D7FF]',但它无法编译,显示为无效范围。我对Unicode正则表达式还不熟悉,以前没有遇到过这个问题。
有没有办法使其编译通过,或者有没有我忘记或尚未学习的正则表达式?

这里编译正常(2.6.5) - NullUserException
你说得对 - 那确实可以编译 - 我以为我正在处理的正则表达式部分有问题。我会发布导致问题的部分。 - spig
重新标记了这个问题,因为这里给出的答案解释了在3.x版本中与2.x版本行为明显不同的问题。在Python 3.x中,这个示例被正确解析为一个范围,包括字面字符F,以及位于' '(空格)和'\xd7'之间的任何内容(它与'\u00d7'表示的内容相同)。如果问题是“为什么范围不包括Unicode代码点0xd7ff?”,那是因为\u转义序列使用恰好四个十六进制数字,而\U使用恰好八个数字 - 这与正则表达式完全无关。 - undefined
2个回答

35

您的 Unicode 范围语法无法达到您的预期。

  1. 使用原始字符串 r'' 可以防止解析 \u 转义字符,正则表达式引擎也不会解析它。在此集合中唯一的范围是 [0-\]

    >>> re.compile(r'[\u0020-\u00d7ff]', re.DEBUG)
    in
      literal 117
      literal 48
      literal 48
      literal 50
      range (48, 117)
      literal 48
      literal 48
      literal 100
      literal 55
      literal 102
      literal 102
    
  2. 将其作为Unicode文字字面量使\u被解析,同时保留其他反斜杠不变(尽管这在此处不是问题),但前导零会引起问题。语法应为\uxxxx\Uxxxxxxxx,因此它被解析为"\u00d7, f, f"。

  3. >>> re.compile(ur'[\u0020-\u00d7ff]', re.DEBUG)
    in
      range (32, 215)
      literal 102
      literal 102
    
  4. 去掉前导零或切换为\U0000d7ff即可解决:

    >>> re.compile(ur'[\u0020-\ud7ff]', re.DEBUG)
    in
      range (32, 55295)
    

1
非常感谢 - 我之前对 Unicode 的所有内容都不了解。所以,它必须是带有小写'u'的4位数和带有大写'U'的8位数,对吗? - spig
4
请注意,此回答是在 Python 2 的背景下提出的。在 Python 3 中,r"example"ur"example" 没有区别。 - Flimm

5

如果您正在使用Python 2.x版本,您应该确保指定一个Unicode字符串(使用u''或内置的"unicode"):

>>> r = re.compile(u'[\u0020-\uD7FF]')
>>> r.search(u'foo \uD7F0 bar')
<_sre.SRE_Match object at 0xb7084950>
r.search(u' ')
<_sre.SRE_Match object at 0xb7084b48>

使用原始字符串(就像您现在使用的r'')会给您一个由“反斜杠” + 字母“u”加数字0组成的(ascii)字符串,然后是...

当\u不够长时,您是否需要'0'字符?比如对于空格,您只需要\u20,但是您需要写\u0020,对吗? - spig
我看到你已经得到了答案,没错,那就是对的 :) - rbp
2
全Unicode怎么办?例如,哥特字母块从U+10330 GOTHIC LETTER AHSA到U+1034A GOTHIC LETTER NINE HUNDRED,但还包括下面的五个代码点,目前没有名称。在Python中如何表达其他编程语言允许您使用\p{Gothic}\p{Script=Gothic}\p{InGothic}\p{Block=Gothic}?例如,在Perl中,/\pN/ && /\p{InGothic}/会产生U+10341 GOTHIC LETTER NINETY和U+1034A GOTHIC LETTER NINE HUNDRED。虽然这在Python中不起作用,但为什么呢? - tchrist
1
如果我理解正确的话,您可以使用大写字母U来表示更大的代码点,填充到8个十六进制数字。例如,在您的示例中U+10330,您将使用u'\U00010330'。 - rbp
2
@tchrist 但是在Python中不起作用,为什么呢? Python的re模块从来没有特别好地处理Unicode,尽管第三方的regex库(https://pypi.org/project/regex/)可以正常工作。 - HackerBoss

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接