正则表达式在孟加拉语单词中找到音节

时间:2012-04-17 11:48:32

标签: python regex unicode nlp

以下是代码:

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

此代码不仅可以纠正错误,还可以解释比以前更多的字符和有效构造。

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

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

2 个答案:

答案 0 :(得分: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与你的正则表达不匹配。

Bengali code chart,你似乎错过了其他一些角色。


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

  1. BanglaAlphabet字典中的字符串缺少u(Unicode)标志。这意味着像\u0995这样的Unicode转义序列不会被转换为Unicode字符。你只需要反斜杠,字母和数字。

  2. BanglaWordPattern正则表达式中,在结尾附近有一个垂直条|,后面没有任何内容。这意味着整个正则表达式看起来像(stuff1|stuff2|stuff3|stuff4|)+。所以实际上有五个替代品,最后一个是空的。当然,空正则表达式匹配任何内容。

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

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

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

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

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

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

    5. 我会写这样的东西:

      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)
      

      但我也会看一下您省略的代码表中的其他Bangla标志。那么U + 0981 BENGALI SIGN CANDRABINDU和U + 0982 BENGALI SIGN ANUSVARA(鼻音元音)怎么样?怎么样的U + 09CD BENGALI SIGN VIRAMA(取消元音)?等等。

答案 1 :(得分: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}
)+$

在每个合取/字母中,获得一个独立的元音或一个辅音,可能后跟一个从属元音,可能在它们之间有一个nukta。

我所做的其他改动:

  • 变量/项目命名,以符合标准Python编码风格;
  • (...)(匹配组)替换为(?:...)(不匹配的组)以获得性能(请参阅文档);
  • 更正了“依赖”的拼写;
  • 将“bangla”改为“bengali”,如英文所示,它是孟加拉语;我更喜欢说英语时使用标准英语名称而不是母语发音,必要时使用Anglicised-例如。法语而不是lefrançais。另一方面,我确实意识到孟加拉语经常被说英语的人称为孟加拉语。