在python正则表达式中使用Unicode列表

时间:2018-09-11 09:41:37

标签: python regex unicode

我有一个Unicode格式的字形列表,并希望从它们中编译一个级联字符串,以使用正则表达式类进行搜索,例如:

>>> letters = [u'\ufb02', u'\u0106', u'\u2010', u'\u0302', u'\u0116', u' ', u'\u0126', u'\xab', u'0', u'\u0136', u'\xbb', u'@', u'\u02c7', u'\u0146', u'\xcb', u'P', u'\u0156', u'\xdb', u'`', u'\u0166', u'\xeb', u'\u20bc', u'p', u'\u0312', u'\u0176', u'\xfb', u'\u0101', u'\u1e84', u'\u0111', u'\u0121', u'+', u'\u0131', u'\xb0', u'\u0237', u';', u'\u0141', u'\xc0', u'\u2020', u'K', u'v', u'\u0151', u'\xd0', u'[', u'\u02dc', u'\u0161', u'\xe0', u'\u1ee4', u'\u01e6', u'k', u'\u0171', u'\xf0', u'{', u'\u0100', u'\u1e85', u'\u2030', u'\u030c', u'\u0110', u'\u2212', u'\xa1', u'\u0120', u'\u2026', u'\u0130', u'\u0232', u'6', u'\xc1', u'\u0140', u'F', u'\xd1', u'\u0150', u'V', u'\u02dd', u'\xe1', u'\u0160', u'\u1ee5', u'f', u'\u01eb', u'\xf1', u'\u0170', u'\u0272', u'\u2076', u'\u01fb', u'\u0307', u'\u010b', u'\u011b', u'!', u'\u0327', u'\xa6', u'\u012b', u'1', u'\u0337', u'\xb6', u'\u013b', u'A', u'\u2021', u'\u2077', u'\xc6', u'\u014b', u'\u1eca', u'Q', u'\xd6', u'\u015b', u'a', u'\xe6', u'\u016b', u'q', u'\xf6', u'\u017b', u'\u1e83', u'\u0102', u'\u0306', u'\u0112', u'\u019d', u'\u201c', u'\u0122', u'\xa7', u'\u0326', u',', u'\xb7', u'<', u'\u0142', u'\xc7', u'L', u'\u2039', u'\u0152', u'\xd7', u'\u02db', u'\\', u'&', u'\u0162', u'\xe7', u'l', u'\u1ef3', u'\u0172', u'\xf7', u'\u01fd', u'|', u'\ufb01', u'\u010d', u'\u0192', u'\u021b', u'\u011d', u"'", u'\u2070', u'\u012d', u'\u20ac', u'7', u'\u1eb8', u'\u013d', u'\xbc', u'G', u'\u014d', u'\xcc', u'"', u'W', u'\u2078', u'\u015d', u'\xdc', u'g', u'\u016d', u'\xec', u'w', u'\u1ef8', u'\u017d', u'\xfc', u'\u0300', u'\u010c', u'\u011c', u'\u2022', u'\u20ad', u'\u012c', u'2', u'\u1eb9', u'\xbd', u'\u013c', u'B', u'\xcd', u'\u014c', u'R', u'\xdd', u'\u015c', u'b', u'\u01e7', u'\u20bd', u'\xed', u'\u016c', u'r', u'\u1ef9', u'\xfd', u'\u017c', u'\u0107', u'\u030b', u'\u0117', u'\u201d', u'\u1e9e', u'\xa2', u'\u0127', u'-', u'\xb2', u'\u0137', u'\u203d', u'\xc2', u'\u0147', u'\u02c6', u'M', u'y', u'\xd2', u'\u0157', u'\u2032', u']', u'\xe2', u'\u0167', u'm', u'\xf2', u'\u0177', u'}', u'\u01fc', u'\u030a', u'\u010e', u'\u2018', u'\u011e', u'\xa3', u'(', u'\u2033', u'\u012e', u'\xb3', u'8', u'\u013e', u'\xc3', u'H', u'\u014e', u'\xd3', u'X', u'\u015e', u'\xe3', u'h', u'\u016e', u'\xf3', u'x', u'\u017e', u'\u0109', u'\u2013', u'\u0119', u'#', u'\u0129', u'\xa8', u'3', u'\u0335', u'\u0139', u'\xb8', u'\u1ebc', u'C', u'\xc8', u'\u1ecc', u'S', u'\u2122', u'\u0159', u'\xd8', u'c', u'\u0169', u'\xe8', u's', u'\u0179', u'\xf8', u'\u01fe', u'\u0304', u'\u0108', u'\u0118', u'\u021a', u'\u201e', u'\u20a9', u'\u0128', u'.', u'\xb9', u'\u1ebd', u'>', u'\xc9', u'\u0148', u'\u1ecd', u'N', u'\xd9', u'\u0158', u'^', u'\xe9', u'\u0168', u'n', u'\u20bf', u'\xf9', u'\u0178', u'~', u'\u0103', u'\u1e82', u'\u0113', u'\u2215', u'\u2019', u'\u2044', u'\u0123', u')', u'\xae', u'9', u'\xbe', u'\u0143', u'I', u'\xce', u'\u0153', u'Y', u'\u02da', u'\xde', u'\u0163', u'i', u'\xee', u'\u0173', u'\u1ef2', u'\u2079', u'\xfe', u'\u20aa', u'\u010a', u'\u2014', u'\u0218', u'\u011a', u'$', u'\u012a', u'\xaf', u'4', u'\u013a', u'\xbf', u'D', u'\u2248', u'\u1ecb', u'\u014a', u'\xcf', u'T', u'\u015a', u'\xdf', u'\u20ba', u'd', u'=', u'\u016a', u'\xef', u't', u'\u017a', u'\xff', u'\u1e80', u'\u0105', u'\u0115', u'\u1ea0', u'\u0125', u'\xa4', u'\u203a', u'/', u'\u0233', u'\u0135', u'\xb4', u'?', u'\u2074', u'\u0145', u'\xc4', u'O', u'\u0155', u'\xd4', u'\u02d8', u'_', u'\u0165', u'\xe4', u'\u01ea', u'o', u'\xa9', u'\u0175', u'\xf4', u'\u01fa', u'\u1e81', u'\u0301', u'\u0104', u'\u0308', u'\u018f', u'\u0114', u'\u201a', u'\u1ea1', u'\xa5', u'\u0124', u'\u0328', u'*', u'\u0134', u'\u0338', u':', u'\xc5', u'\u0144', u'J', u'\u20b9', u'\xd5', u'\u0154', u'\u02d9', u'Z', u'\xe5', u'\u0164', u'j', u'\xf5', u'\u0174', u'z', u'\u01ff', u'\u0303', u'\u010f', u'\u0219', u'\u011f', u'\u0323', u'%', u'\xaa', u'\u012f', u'5', u'u', u'\xba', u'\u013f', u'E', u'\xca', u'\u014f', u'U', u'\u0259', u'\xda', u'\u015f', u'e', u'\xea', u'\u016f', u'\u2075', u'\xfa', u'\u017f']
>>> regex = re.compile("[" + "".join(letters) + "]+")

对于此列表,我收到以下错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/re.py", line 194, in compile
    return _compile(pattern, flags)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/re.py", line 251, in _compile
    raise error, v # invalid expression
sre_constants.error: bad character range

为什么以及列表中的哪个unicode字符会破坏regex编译调用?

1 个答案:

答案 0 :(得分:1)

您的输入中有一个-字符,以及用于创建范围表达式的前和后字符(其中,第一个和第二个之间的所有代码点也都匹配):

>>> print(letters[195:198])
[u'\u0127', u'-', u'\xb2']

因为U + 0127实际上是一个比U + 00B2高 的代码点,所以会引起异常:

>>> re.compile("[" + "".join(letters[195:198]) + "]+")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mj/Development/venvs/stackoverflow-2.7/lib/python2.7/re.py", line 194, in compile
    return _compile(pattern, flags)
  File "/Users/mj/Development/venvs/stackoverflow-2.7/lib/python2.7/re.py", line 251, in _compile
    raise error, v # invalid expression
sre_constants.error: bad character range

通过将letters分成较小的子集(每次将列表减半),直到我得到仍然可以产生的最小列表,我找到了本节。

您可能希望转义短划线而不是将其解释为范围。出于相同的原因,您还需要转义任何反斜杠和]字符;那些在集合中也有特殊的意义:

setmeta = {u'\\': u'\\\\', u'-': u'\\-', u']': u'\\]'}
regex = re.compile("[" + "".join([setmeta.get(l, l) for l in letters]) + "]+")

在逃脱了这些元字符的情况下,您的letters列表可以变成正则表达式:

>>> re.compile("[" + "".join([setmeta.get(l, l) for l in letters]) + "]+")
<_sre.SRE_Pattern object at 0x7f8442503740>