4

这是代码:

BanglaAlphabet = {
    'Consonant'                   : '[\u0995-\u09B9\u09CE\u09DC-\u09DF]',
    'IndependantVowel'            : '[\u0985-\u0994]',
    'DependantVowel'              : '[\u09BE-\u09CC\u09D7]',
    'Nukta'                       : '[\u09BC]'
}
BanglaWordPattern = ur"""(
    ({DependantVowel}{Nukta}{Consonant}) |
    ({DependantVowel}{Consonant}) |
    {IndependantVowel} |
    {Consonant} |
)+""".format(**BanglaAlphabet)
BanglaWordPattern = re.compile(BanglaWordPattern, re.VERBOSE)

匹配是通过以下方式完成的:

re.match(BanglaWordPattern, w[::-1])

这意味着在从右到左匹配时匹配有效的孟加拉语单词。

但是,它会匹配无效的单词,例如 োগাড় 和 িদগ。

可能是什么问题呢?

编辑

在@GarethRees 和@ChrisMorgan 建议的多次更正之后,我最终得到:

bangla_alphabet = dict(
    consonant         = u'[\u0995-\u09b9\u09ce\u09dc-\u09df]',
    independent_vowel = u'[\u0985-\u0994]',
    dependent_vowel   = u'[\u09be-\u09cc\u09d7]',
    dependent_sign    = u'[\u0981-\u0983\u09cd]',
    virama            = u'[\u09cd]'
)
bangla_word_pattern = re.compile(ur'''(?:
    {consonant}
    ({virama}{consonant})?
    ({virama}{consonant})?
    {dependent_vowel}?
    {dependent_sign}?
    |
    {independent_vowel}
    {dependent_sign}?
)+

现在的匹配是:

bangla_word_pattern.match(w)

这段代码不仅纠正了错误,而且比以前解释了更多的字符和有效的结构。

我很高兴地报告它按预期工作。因此,此代码现在用作验证孟加拉语单词语法的非常基本的正则表达式。

有几个特殊规则/例外未实施。我将研究这些并将它们逐步添加到这个基本结构中。

许多 ''.format(**bangla_alphabet), re.VERBOSE)

现在的匹配是:

xCodexBlockxPlacexHolderx

这段代码不仅纠正了错误,而且比以前解释了更多的字符和有效的结构。

我很高兴地报告它按预期工作。因此,此代码现在用作验证孟加拉语单词语法的非常基本的正则表达式。

有几个特殊规则/例外未实施。我将研究这些并将它们逐步添加到这个基本结构中。

4

2 回答 2

3

您的字符串কয়া由以下字符组成:

>>> import unicodedata
>>> map(unicodedata.name, u'কয়া')
['BENGALI LETTER KA', 'BENGALI LETTER YA', 'BENGALI SIGN NUKTA', 'BENGALI VOWEL SIGN AA']

U+09BC BENGALI SIGN NUKTA 与您的正则表达式不匹配。

查看孟加拉语代码表,您似乎可能遗漏了一些其他字符。


好的,回答您更新的问题。你犯了三个错误:

  1. 您在字典中的字符串BanglaAlphabet缺少u(Unicode) 标志。这意味着 Unicode 转义序列\u0995不会被翻译成 Unicode 字符。你只会得到反斜杠、字母和数字。

  2. BanglaWordPattern正则表达式中,靠近末尾有一个竖线|,后面没有任何内容。这意味着整个正则表达式看起来像(stuff1|stuff2|stuff3|stuff4|)+. 所以真的有五种选择,最后一种是空的。当然,空的正则表达式匹配任何东西。

  3. 您实际上并没有查看程序的结果来查看它实际匹配的内容。如果您编写m = re.match(BanglaWordPattern, w[::-1]); print m.group(0),您会看到实际匹配的是空字符串。

我认为以下也是错误,但是您还没有解释您要做什么,所以我不太自信:

  1. 您正在向后进行匹配,这是不必要的。如果您将模式翻转并向前匹配,将会更简单、更容易理解。

  2. 您正在正则表达式中使用捕获括号。如果您不需要结果,请改用非捕获括号(?:...)

  3. 无论如何,内部的括号是不必要的。

  4. 您没有将正则表达式的末尾锚定在单词边界或字符串的末尾。

我会写这样的东西:

import re

bangla_categories = dict(
    consonant         = u'[\u0995-\u09B9\u09CE\u09DC-\u09DF]',
    independent_vowel = u'[\u0985-\u0994]',
    dependent_vowel   = u'[\u09BE-\u09CC\u09D7]',
    nukta             = u'[\u09BC]',
)

bangla_word_re = re.compile(ur"""(?:
    {consonant}{nukta}{dependent_vowel} |
    {consonant}{dependent_vowel} |
    {independent_vowel} |
    {consonant}
)+(?:\b|$)""".format(**bangla_categories), re.VERBOSE)

但我也会查看您省略的代码图表中的其他孟加拉语标志。U+0981 BENGALI SIGN CANDRABINDU 和 U+0982 BENGALI SIGN ANUSVARA(使元音鼻化)呢?U+09CD BENGALI SIGN VIRAMA(取消元音)怎么样?等等。

于 2012-04-17T11:56:58.833 回答
1

你所拥有的有几个问题:

  • 您的正则表达式最终会在其中包含文字\u0995等,因为它们不是 Unicode 字符串;您需要包含实际的 Unicode 字符。

  • 您希望$在正则表达式的末尾,以便它只匹配整个字符串。

  • 您的组中有一个空字符串是有效的(通过用管道结束第一组,留下一个空选项)。这与缺少$符号相结合,意味着它不起作用。

  • 它不完整(正如 Gareth 所观察到的)。

另请注意,您也可以在获得已编译的正则表达式对象后bengali_word_pattern.match(s)代替。re.match(bengali_word_pattern, s)

bengali_alphabet = {
    'consonant': u'[\u0995-\u09B9\u09CE\u09DC-\u09DF]',
    'independent_vowel': u'[\u0985-\u0994]',
    'dependent_vowel': u'[\u09BE-\u09CC\u09D7]',
    'nukta': u'\u09BC'
}

bengali_word_pattern = ur'''^(?:
    (?:{dependent_vowel}{nukta}{consonant}) |
    (?:{dependent_vowel}{consonant}) |
    {independent_vowel} |
    {consonant}
)+$'''.format(**bengali_alphabet)
bengali_word_pattern = re.compile(bengali_word_pattern, re.VERBOSE)

现在,

>>> bengali_word_pattern.match(u'বাংলা'[::-1])

由于“ং”字符U+0982,这个不起作用;它不在您的任何范围内。不确定该位属于哪个类别;如果我们只是取出冒犯性的角色,它就可以工作。(谷歌翻译告诉我,结果词可以翻译成“手镯”——我不知道,我需要问我姐姐;我能如实说的大约是আমি বাংলা বলতে পারি না。几乎我所知道的都是方便মুরগি চোর 之类的日常用语。而且它的第一个单词还包含一个迄今为止遗漏的元音。无论如何,这无关紧要。)

>>> bengali_word_pattern.match(u'বালা')
<_sre.SRE_Match object at 0x7f00f5bf9620>

它也适用于“鸡贼”短语。

>>> [bengali_word_pattern.match(w[::-1]) for w in u'মুরগি চোর'.split()]
[<_sre.SRE_Match object at 0x7f00f5bf9620>, <_sre.SRE_Match object at 0x7f00f5bf97e8>]

它不匹配这两个不完整单词的例子:

>>> bengali_word_pattern.match(u'োগাড়'[::-1])
>>> bengali_word_pattern.match(u'িদগ'[::-1])

在这一点上,我也会承认自己对为什么要向后解析字符串感到困惑;我会认为向前完成它是有意义的(这个正则表达式工作正常,那么你不需要使用[::-1]):

^(?:
    {consonant}
    (?:
        {nukta}?
        {dependent_vowel}
    )?
    |
    {independent_vowel}
)+$

在每个连词/字母处,获得一个独立元音或一个辅音,可能后跟一个从属元音,它们之间可能有一个元音。

我所做的其他更改:

  • 变量/项目命名,以适应标准 Python 编码风格;
  • (...)将(匹配组)替换为(?:...)(非匹配组)以提高性能(参见文档);
  • 更正了“依赖”的拼写;
  • 将“bangla”改为“bengali”,因为英语是孟加拉语;在说英语时,我更喜欢使用标准的英语名称而不是母语发音,如有必要,可以使用英语——例如法语而不是le français。另一方面,我确实意识到孟加拉语经常被说英语的人称为孟加拉语。
于 2012-04-17T14:37:04.643 回答