正则表达式获取具有特定字母的所有单词列表(unicode字形)

Ash*_*han 6 python regex unicode tamil indic

我正在为FOSS语言学习计划编写Python脚本.假设我有一个XML文件(或保持简单,一个Python列表),其中包含特定语言的单词列表(在我的例子中,单词是泰米尔语,它使用基于Brahmi的印度语脚本).

我需要绘制那些可以使用这些字母拼写的单词的子集.

一个英文例子:

words = ["cat", "dog", "tack", "coat"] 

get_words(['o', 'c', 'a', 't']) should return ["cat", "coat"]
get_words(['k', 'c', 't', 'a']) should return ["cat", "tack"]
Run Code Online (Sandbox Code Playgroud)

泰米尔语的例子:

words = [u"????", u"????", u"????", u"?????"]

get_words([u'?', u'?', u'?', u'??')  should return [u"????", u"????")
get_words([u'?', u'??', u'?') should return [u"????"] 
Run Code Online (Sandbox Code Playgroud)

返回单词的顺序或输入字母的顺序不应有所不同.

虽然我理解unicode代码点和字形之间的区别,但我不确定它们是如何在正则表达式中处理的.

在这种情况下,我想只匹配由输入列表中的特定字素组成的那些单词,而不是其他任何内容(即字母后面的标记只应该跟随该字母,但字母本身可以出现在任何字母中.订购).

jfs*_*jfs 5

要支持可以跨越多个Unicode代码点的字符:

# -*- coding: utf-8 -*-
import re
import unicodedata
from functools import partial

NFKD = partial(unicodedata.normalize, 'NFKD')

def match(word, letters):
    word, letters = NFKD(word), map(NFKD, letters) # normalize
    return re.match(r"(?:%s)+$" % "|".join(map(re.escape, letters)), word)

words = [u"????", u"????", u"????", u"?????"]
get_words = lambda letters: [w for w in words if match(w, letters)]

print(" ".join(get_words([u'?', u'?', u'?', u'??'])))
# -> ???? ????
print(" ".join(get_words([u'?', u'??', u'?'])))
# -> ????
Run Code Online (Sandbox Code Playgroud)

它假设一个单词中可以使用相同的字符零次或多次.

如果您只想要包含确切给定字符的单词:

import regex # $ pip install regex

chars = regex.compile(r"\X").findall # get all characters

def match(word, letters):
    return sorted(chars(word)) == sorted(letters)

words = ["cat", "dog", "tack", "coat"]

print(" ".join(get_words(['o', 'c', 'a', 't'])))
# -> coat
print(" ".join(get_words(['k', 'c', 't', 'a'])))
# -> tack
Run Code Online (Sandbox Code Playgroud)

注意:cat在这种情况下输出中没有,因为cat不使用所有给定的字符.


归一化意味着什么?你能解释一下re.match()正则表达式的语法吗?

>>> import re
>>> re.escape('.')
'\\.'
>>> c = u'\u00c7'
>>> cc = u'\u0043\u0327'
>>> cc == c
False
>>> re.match(r'%s$' % (c,), cc) # do not match
>>> import unicodedata
>>> norm = lambda s: unicodedata.normalize('NFKD', s)
>>> re.match(r'%s$' % (norm(c),), norm(cc)) # do match
<_sre.SRE_Match object at 0x1364648>
>>> print c, cc
Ç C?
Run Code Online (Sandbox Code Playgroud)

没有标准化c而且cc不匹配.角色来自unicodedata.normalize()文档.