使用正则表达式

时间:2016-04-19 10:19:09

标签: regex python-2.7 unicode utf-8 diacritics

我使用的是包含letter ü的以下文字摘要:

test für fur test

以下是代码:

import re

for m in re.finditer(r, line, re.IGNORECASE | re.UNICODE):
    print 'match:  ', m.group(0)
    print 'offset: ', m.start()

有三个正则表达式:

r = ur'\bf(\u0075)r\b'    # finds 'fur', as expected
r = ur'\bf(\xc3\xbc)r\b'  # finds 'für', as expected
r = ur'\bf(\u00FC)r\b'    # does not find 'für'

表达式#1和#3相似;唯一的区别是Unicode点(u vs ü)。 #3为什么不起作用?

我可以使用#2,但它的可读性较差。

2 个答案:

答案 0 :(得分:2)

以下是我的测试结果。

>>> print re.findall(ur'\bf(\u0075)r\b', "test für fur test", re.I|re.U)
['u']
>>> print re.findall(ur'\bf(\xc3\xbc)r\b', "test für fur test", re.I|re.U)
['\xc3\xbc']
>>> print re.findall(ur'\bf(\u00FC)r\b', "test für fur test", re.I|re.U)
[]

这些完全符合您的结果。我注意到第二个案例的匹配是['\xc3\xbc'],然后它击中了我。 "test für fur test"是非unicode字符串。

这是我用unicode字符串进行的第二组测试。

>>> print re.findall(ur'\bf(\u0075)r\b', u"test für fur test", re.I|re.U)
[u'u']
>>> print re.findall(ur'\bf(\xc3\xbc)r\b', u"test für fur test", re.I|re.U)
[]
>>> print re.findall(ur'\bf(\u00FC)r\b', u"test für fur test", re.I|re.U)
[u'\xfc']

正则表达式匹配字符串中的二进制表示。所以unicode字符串匹配unicode字符,非unicode字符串匹配UTF-8编码字符。

如果您无法选择使用的刺痛类型,则可以始终使用unicode()

>>> print re.findall(ur'\bf(\u00FC)r\b', unicode("test für fur test", "utf-8"), re.I|re.U)
[u'\xfc']

在你的情况下

for m in regex.finditer(r, unicode(line, "utf-8"), regex.IGNORECASE | regex.UNICODE):
    print 'match:  ', m.group(0)
    print 'offset: ', m.start()

注意

根据.py文件的文件编码,ur'\bf(ü)r\b'也应该有效。

>>> print re.findall(ur'\bf(ü)r\b', u"test für fur test", re.I|re.U)
[u'\xfc']

答案 1 :(得分:2)

我觉得你在这里让自己感到困惑。您正在使用的字符串显然不是Unicode字符串。

如果是,您将按预期获得\u00fc

>>> import re
>>> m = re.search(ur'f(\xc3\xbc|\u0075|\u00fc)r', u'für')
>>> m.group(1)
u'\xfc'

您仍然需要满足Unicode等效性。完全分解的等效U+00FC是常规u,后跟COMBINING DIAERESIS (U+0308)。可能你会想要运行unicodedata.normalize('NFC', thing)并确保你的正则表达式总是寻找组合的等价物(或相反地去'NFD'并完全分解);或者转换到据称可以更好地处理这个问题的regex module

如果您正在处理UTF-8并且您知道自己是,那么通常建议您在将其读入Python后将其解码为Unicode字符串。参见例如http://nedbatchelder.com/text/unipain.html