python - 使用 TRE : strange unicode behavior 在 python 中近似 RegEx

标签 python regex fuzzy-comparison tre-library

我正在尝试使用 TRE - python 中的库来匹配拼写错误的输入。
重要的是,它确实可以很好地处理 utf-8 编码的字符串。

一个例子:
德国首都的名字叫柏林,但从发音上看是一样的,如果写成“Bärlin”

到目前为止它是有效的,但是如果非 ASCII 字符位于检测到的字符串的第一个或第二个位置,则范围和检测到的字符串本身都不正确。

# -*- coding: utf-8 -*-
import tre

def apro_match(word, list):
    fz = tre.Fuzzyness(maxerr=3)
    pt = tre.compile(word)
    for i in l:
        m = pt.search(i,fz)
        if m:
            print m.groups()[0],' ', m[0]

if __name__ == '__main__':
    string1 = u'Berlín'.encode('utf-8')
    string2 = u'Bärlin'.encode('utf-8')    
    string3 = u'B\xe4rlin'.encode('utf-8')
    string4 = u'Berlän'.encode('utf-8')
    string5 = u'London, Paris, Bärlin'.encode('utf-8')
    string6 = u'äerlin'.encode('utf-8')
    string7 = u'Beälin'.encode('utf-8')

    l = ['Moskau', string1, string2, string3, string4, string5, string6, string7]

    print '\n'*2
    print "apro_match('Berlin', l)"
    print "="*20
    apro_match('Berlin', l)
    print '\n'*2

    print "apro_match('.*Berlin', l)"
    print "="*20
    apro_match('.*Berlin', l)

输出

apro_match('Berlin', l)
====================
(0, 7)   Berlín
(1, 7)   ärlin
(1, 7)   ärlin
(0, 7)   Berlän
(16, 22)   ärlin
(1, 7)   ?erlin
(0, 7)   Beälin



apro_match('.*Berlin', l)
====================
(0, 7)   Berlín
(0, 7)   Bärlin
(0, 7)   Bärlin
(0, 7)   Berlän
(0, 22)   London, Paris, Bärlin
(0, 7)   äerlin
(0, 7)   Beälin

不是正则表达式 '.*Berlin' 它工作正常,而正则表达式 'Berlin'

u'Bärlin'.encode('utf-8')    
u'B\xe4rlin'.encode('utf-8')
u'äerlin'.encode('utf-8')

不工作,而

u'Berlín'.encode('utf-8')
u'Berlän'.encode('utf-8')
u'London, Paris, Bärlin'.encode('utf-8')
u'Beälin'.encode('utf-8')

按预期工作。

我的编码有什么问题吗?你知道什么技巧吗?

最佳答案

您可以使用新的 regex 库,它支持 Unicode 6.0 和模糊匹配:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from itertools import ifilter, imap
import regex as re

def apro_match(word_re, lines, fuzzy='e<=1'):
    search = re.compile(ur'('+word_re+'){'+fuzzy+'}').search
    for m in ifilter(None, imap(search, lines)):
        print m.span(), m[0]

def main():
    lst = u'Moskau Berlín Bärlin B\xe4rlin Berlän'.split()
    lst += [u'London, Paris, Bärlin']
    lst += u'äerlin Beälin'.split()
    print
    print "apro_match('Berlin', lst)"
    print "="*25
    apro_match('Berlin', lst)
    print 
    print "apro_match('.*Berlin', lst)"
    print "="*27
    apro_match('.*Berlin', lst)

if __name__ == '__main__':
    main()

'e<=1'意味着最多允许任何一种错误。错误分为三种类型:

  • 插入,用“i”表示
  • 删除,用“d”表示
  • 替换,用“s”表示

输出

apro_match('Berlin', lst)
=========================
(0, 6) Berlín
(0, 6) Bärlin
(0, 6) Bärlin
(0, 6) Berlän
(15, 21) Bärlin
(0, 6) äerlin
(0, 6) Beälin

apro_match('.*Berlin', lst)
===========================
(0, 6) Berlín
(0, 6) Bärlin
(0, 6) Bärlin
(0, 6) Berlän
(0, 21) London, Paris, Bärlin
(0, 6) äerlin
(0, 6) Beälin

关于python - 使用 TRE : strange unicode behavior 在 python 中近似 RegEx,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6946407/

相关文章:

python - += : 'int' and 'str' on pycharm 不受支持的操作数类型

python - 在 python 中过滤掉电子邮件和域的最佳方法

c# - 即使字符串匹配,正则表达式验证也会显示错误

c - | (或者C语言中的正则表达式中运算符不起作用)

image - 如何判断图像是否为 90% 黑色?

string - 名称的近似字符串匹配算法

php - 模糊文本搜索 : Regex Wildcard Search Generator?

用于通过脚本内的每个函数编写和附加单个 xls 文档的 Python 脚本。目前它覆盖了工作表

python - qt 和 PyQt4 的区别

python - 如何统一获取类和函数的字符串表示?