具有匹配组的Python正则表达式子函数

时间:2014-01-02 20:51:18

标签: python regex

我正在尝试使用python正则表达式子函数,但我遇到了一些麻烦。下面是我正在使用的代码。

 string = 'á:tdfrec'
 newString = re.sub(ur"([aeioäëöáéíóàèìò])([aeioäëöáéíóúàèìò]):", ur"\1:\2", string)
 #newString = re.sub(ur"([a|e|i|o|ä|ë|ö|á|é|í|ó|à|è|ì|ò])([a|e|i|o|ä|ë|ö|á|é|í|ó|ú|à|è|ì|ò]):", ur"\1:\2", string)
 print newString
 # a:́tdfrec is printed

所以上面的代码没有按我想要的方式工作。它没有正确显示,但打印的字符串具有超过:的精确度。正则表达式声明正在将精度重音从a移到:之上。对于我声明这个正则表达式的字符串不应该被应用。我对此正则表达式声明的意图仅适用于以下示例:

 aä:dtcbd becomes a:ädtcbd
 adfseì:gh becomes adfse:ìgh 
 éò:fdbh becomes é:òfdbh

但我的正则表达式声明正在应用,我不希望它。我认为我的问题是:后跟的第二个字符集(即á:)是导致正则表达式语句被应用的原因。我已经盯着这一段时间并尝试了一些其他的东西,我觉得这应该有效,但我错过了一些东西。任何帮助表示赞赏!

带有re.UNICODE标志的以下代码也无法达到所需的输出:

>>> import re
>>> original = u'á:tdfrec'
>>> pattern = re.compile(ur"([aeioäëöáéíóàèìò])([aeioäëöáéíóúàèìò]):", re.UNICODE)
>>> print pattern.sub(ur'\1:\2', string)
á:tdfrec

是否因为变音符号和les misérable的{​​{3}}示例?在扭转它之后,变音符号出现了错误的字符:

>>> original = u'les misérable'
>>> print ''.join([i for i in reversed(original)])
elbarésim sel

1 个答案:

答案 0 :(得分:2)

编辑绝对是组合变音符号的问题,您需要规范化正则表达式和您尝试匹配的字符串。例如:

import unicodedata

regex = unicodedata.normalize('NFC', ur'([aeioäëöáéíóàèìò])([aeioäëöáéíóúàèìò]):')
string = unicodedata.normalize('NFC', u'aä:dtcbd')
newString = re.sub(regex, ur'\1:\2', string)

这是一个示例,说明了在没有规范化的情况下可能遇到问题的原因。字符串u'á'可以是单个代码点LATIN SMALL LETTER A WITH ACCUTE(U + 00E1),也可以是两个代码点,LATIN SMALL LETTER A(U + 0061),然后是COMBINING ACUTE ACCENT(U + 0301)。这些可能看起来相同,但它们在正则表达式中会有非常不同的行为,因为您可以将组合重音符合为自己的角色。这就是字符串'á:tdfrec'发生的情况,在第1组中捕获了常规“a”,在第2组中捕获了组合变音符号。

通过规范化正则表达式和匹配的字符串,确保不会发生这种情况,因为NFC规范化将使用单个等效字符替换变音符号和前面的字符。

以下原始答案。


我认为您的问题是,您尝试进行替换的字符串是字节字符串,而不是Unicode字符串。

如果这些是字符串文字,请确保使用u前缀,例如string = u'aä:dtcbd'。如果它们不是文字,则需要对它们进行解码,例如: string = string.decode('utf-8')(尽管您可能需要使用不同的编解码器)。

你可能也应该normalize your string,因为部分问题可能与变音符号的组合有关。

请注意,在这种情况下,re.UNICODE标志不会产生影响,因为这只会改变\w\d等字符类缩写的含义。这里重要的是,如果您使用的是Unicode正则表达式,它应该应用于Unicode字符串。