如何为任意范围的代理项对创建正则表达式模式



在"窄"Python构建中,我们应该使用特殊的正则表达式模式来匹配代理项对的范围。此模式可能相当复杂:

# Pattern we want:
pattern = '[U000105c0-U0001cb40]'
# Pattern we should use in "narrow" build:
pattern = '(?:uD801[uDDC0-uDFFF]|[uD802-uD831][uDC00-uDFFF]|uD832[uDC00-uDF40])'

但是如何为给定的任意代理项范围(例如 U000105c0 - U0001cb40(创建一个?

创建此模式的算法是什么?

Python中是否有现成的解决方案?

安装 http://www.regexformat.com 应用程序。
(适用于窗户(

您可以在任何范围内执行以下操作。
只需要一个正则表达式来描述它(或任何内容(。

打开UCD Interface https://i.stack.imgur.com/bNTGV.jpg

在">自定义接收"页上,输入"[x{105c0}-x{1cb40}]

在输出
中选择所需的转换语法(这x{}语法使用(。

单击按钮Get Hex Conversion -> UTF-16(这是一个菜单按钮(

复制"结果"框底部的正则表达式。

 (?:
      x{D801} [x{DDC0}-x{DFFF}] 
   |  [x{D802}-x{D831}] [x{DC00}-x{DFFF}] 
   |  x{D832} [x{DC00}-x{DF40}] 
 )

如果您将其粘贴到其中一个主要应用程序文档中,
并且点击压缩,事实证明

(?:x{D801}[x{DDC0}-x{DFFF}]|[x{D802}-x{D831}][x{DC00}-x{DFFF}]|x{D832}[x{DC00}-x{DF40}])

这里它使用 uXXXX 语法
(?:uD801[uDDC0-uDFFF]|[uD802-uD831][uDC00-uDFFF]|uD832[uDC00-uDF40])

我创建了处理我们可能需要的大多数情况的函数。

Python 2 代码:

from __future__ import absolute_import, division, print_function, unicode_literals
__metaclass__ = type
import struct

def unichar(i):
    """
    unichr for "narrow" builds.
    """
    try:
        return unichr(i)
    except ValueError:
        return struct.pack('i', i).decode('utf-32')

def get_pattern(char_from, char_to):
    """
    Returns regex pattern for unicode chars that handles surrogates in "narrow" builds.
    """
    if all(len(c) == 1 for c in (char_from, char_to)):
        if char_from == char_to:
            return char_from
        else:
            return '[{}-{}]'.format(char_from, char_to)
    elif all(len(c) == 2 for c in (char_from, char_to)):
        f1, f2 = [ord(i) for i in char_from]
        t1, t2 = [ord(i) for i in char_to]
        if t1 - f1 == 0:
            p1 = '{}[{}-{}]'.format(unichar(f1), unichar(f2), unichar(t2))
            return '(?:' + p1 + ')'
        elif t1 - f1 == 1:
            p1 = '{}[{}-uDFFF]'.format(unichar(f1), unichar(f2))
            p3 = '{}[uDC00-{}]'.format(unichar(t1), unichar(t2))
            return '(?:' + '|'.join([p1, p3]) + ')'
        else:
            p1 = '{}[{}-uDFFF]'.format(unichar(f1), unichar(f2))
            p2 = '[{}-{}][uDC00-uDFFF]'.format(unichar(f1+1), unichar(t1-1), unichar(f2))
            p3 = '{}[uDC00-{}]'.format(unichar(t1), unichar(t2))
            return '(?:' + '|'.join([p1, p2, p3]) + ')'
    else:
        raise ValueError('Range is not supported by this function {}-{}'.format(char_from, char_to))

# Example:
if __name__ == '__main__':
    print(repr(get_pattern('U000105c0', 'U0001cb40')))
    # (?:ud801[uddc0-udfff]|[ud802-ud831][udc00-udfff]|ud832[udc00-udf40])

最新更新