匹配大写字母/特殊字符/Unicode/越南语字符的正则表达式

5

我遇到了一个问题。实际上,我正在处理越南文本,并且想要找到包含大写字母的每个单词。当我使用“re”模块时,我的函数(temp)无法捕获像“Đà”这样的单词。另一种方法(temp2)是逐个字符检查,虽然可以工作,但因为我必须将句子拆分成单词,所以速度很慢。

因此,我想知道是否有一种方法可以使用“re”模块来捕获所有特殊的大写字母。

我有两种方式:

def temp(sentence):
    return re.findall(r'[a-z]*[A-Z]+[a-z]*', sentence)


lis=word_tokenize(sentence)
def temp2(lis):
    proper_noun=[]
    for word in lis:
        for letter in word:
            if letter.isupper():
                proper_noun.append(word)
                break
    return proper_noun

输入:

'nous avons 2 Đồng et 3 Euro'

预期输出:

['Đồng','Euro']

谢谢!

@PauloScardine Python 3.6.5 - huseyin39
1
这是一个重复的问题: https://dev59.com/9loV5IYBdhLWcg3weux1 - blhsing
@blhsing 不是的,他只想找到大写字母而不是包含这些字母的单词。 - huseyin39
@blhsing 对不起,我不知道"re.compile"是什么意思。所以两种解决方案都可以。谢谢。 - huseyin39
@WiktorStribiżew 我所处理的数据没有这种类型的数据,但我同意你的解决方案更完整。 - huseyin39
显示剩余7条评论
3个回答

5
你可以使用这个正则表达式:
\b\S*[AĂÂÁẮẤÀẰẦẢẲẨÃẴẪẠẶẬĐEÊÉẾÈỀẺỂẼỄẸỆIÍÌỈĨỊOÔƠÓỐỚÒỒỜỎỔỞÕỖỠỌỘỢUƯÚỨÙỪỦỬŨỮỤỰYÝỲỶỸỴAĂÂÁẮẤÀẰẦẢẲẨÃẴẪẠẶẬĐEÊÉẾÈỀẺỂẼỄẸỆIÍÌỈĨỊOÔƠÓỐỚÒỒỜỎỔỞÕỖỠỌỘỢUƯÚỨÙỪỦỬŨỮỤỰYÝỲỶỸỴAĂÂÁẮẤÀẰẦẢẲẨÃẴẪẠẶẬĐEÊÉẾÈỀẺỂẼỄẸỆIÍÌỈĨỊOÔƠÓỐỚÒỒỜỎỔỞÕỖỠỌỘỢUƯÚỨÙỪỦỬŨỮỤỰYÝỲỶỸỴAĂÂÁẮẤÀẰẦẢẲẨÃẴẪẠẶẬĐEÊÉẾÈỀẺỂẼỄẸỆIÍÌỈĨỊOÔƠÓỐỚÒỒỜỎỔỞÕỖỠỌỘỢUƯÚỨÙỪỦỬŨỮỤỰYÝỲỶỸỴAĂÂÁẮẤÀẰẦẢẲẨÃẴẪẠẶẬĐEÊÉẾÈỀẺỂẼỄẸỆIÍÌỈĨỊOÔƠÓỐỚÒỒỜỎỔỞÕỖỠỌỘỢUƯÚỨÙỪỦỬŨỮỤỰYÝỲỶỸỴAĂÂÁẮẤÀẰẦẢẲẨÃẴẪẠẶẬĐEÊÉẾÈỀẺỂẼỄẸỆIÍÌỈĨỊOÔƠÓỐỚÒỒỜỎỔỞÕỖỠỌỘỢUƯÚỨÙỪỦỬŨỮỤỰYÝỲỶỸỴA-Z]+\S*\b

正则表达式演示


正如Wiktor Stribiwez指出的那样,您应该将'\S'更改为'[^\W\d_]',以免捕获'+'等字符... - huseyin39

1

@Rizwan M.Tuman的答案是正确的。我想和你分享三个函数在处理10万个句子时的执行速度。

lis=word_tokenize(sentence)
def temp(lis):
    proper_noun=[]
    for word in lis:
        for letter in word:
            if letter.isupper():
                proper_noun.append(word)
                break
    return proper_noun

def temp2(sentence):
    return re.findall(r'[a-z]*[A-Z]+[a-z]*', sentence)

def temp3(sentence):
    return re.findall(capital_letter,sentence)

通过这种方式:
start_time = time.time()
for k in range(100000):
    temp2(sentence)
print("%s seconds" % (time.time() - start_time))

这里是结果:

>>Check each character of a list of words if it is a capital letter (.isupper())
(sentence has already been splitted into words)
0.4416656494140625 seconds

>>Function with re module which finds normal capital letters [A-Z] :
0.9373950958251953 seconds

>>Function with re module which finds all kinds of capital letters :
1.0783331394195557 seconds

1

要匹配仅包含至少1个大写Unicode字母的1个或多个字母块,您可以使用

import re, sys, unicodedata

pLu = '[{}]'.format("".join([chr(i) for i in range(sys.maxunicode) if chr(i).isupper()]))
p = re.compile(r"[^\W\d_]*{Lu}[^\W\d_]*".format(Lu=pLu))

sentence = 'nous avons 2 Đồng et 3 Ęułro.+++++++++++++++Next line'
print(p.findall(sentence))
# => ['Đồng', 'Ęułro', 'Next']

pLu是一个Unicode字母字符类模式,使用unicodedata动态构建。它依赖于Python版本,使用最新版本可以包括尽可能多的Unicode大写字母(详情请参见此答案)。[^\W\d_]是匹配任何Unicode字母的构造。因此,该模式匹配任何0个或多个Unicode字母,后跟至少1个Unicode大写字母,然后再跟任何0个或多个Unicode字母。

请注意,您原来的r'[a-z]*[A-Z]+[a-z]*'只会在此输入中找到Next

print(re.findall(r'[a-z]*[A-Z]+[a-z]*', sentence)) # => ['Next']

请查看Python演示

要匹配整个单词,请使用\b单词边界:

p = re.compile(r"\b[^\W\d_]*{Lu}[^\W\d_]*\b".format(Lu=pLu))

如果您想使用Python 2.x,请不要忘记使用re.U标志使\W\d\b兼容Unicode。然而,建议使用最新的PyPi正则表达式库及其[[:upper:]] / \p{Lu}结构匹配大写字母,因为它将支持最新的Unicode字母列表。

首先感谢您。您的回答对于各种语言都更加方便。然而,我的问题集中在越南语上。此外,这种方法很慢,比另一种方法慢20倍。我已经考虑了Unicode字母的检测。 - huseyin39
@huseyin39 我明白了。不过,我们都忽略了越南语的一个问题:如果字母是多字节字符,则基于 [...] 的正则表达式将无法工作,因为这些字母由基本(拉丁)字母和变音符号组成。如果您想匹配它们,您需要“烹制”一个更复杂的模式。 - Wiktor Stribiżew
你对越南字符的大小是正确的('ẵ'为76字节,而'a'为50字节)。但是,这有关系吗? - huseyin39
@huseyin39 你需要将它们作为备选项添加到分组结构中:([AĂÂÁẮẤÀ..以及其他的预组合字母]|第一个多字节字母|...|第n个多字节字母) - Wiktor Stribiżew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接