为什么正则表达式不起作用?

时间:2013-11-27 20:12:09

标签: python regex cyrillic

我需要用“不间断空格”替换«статья1»,«статьи2»等所有正常空格的出现。 下面的结构工作正常:

 re.sub('(стат.{0,4}) (\d+)', r'\1 \2', text) # 'r' in repl is important, otherwise the word is not replaced correctly, at least for texts in Russian.

然而,我不想重复使用re.sub为«статья»,然后为«пункт»,然后对于几个月的名字,我想要一个带有正则表达式和替换的字典。这是我的代码,但它没有按预期工作:'статья 1 статьи 2'应该看起来像'статья(non-breaking space here)1 статьи(non-breaking space here)2'

 import re

 text = 'статья 1 статьи 2'
 dic = {'(cтат.{0,4}) (\d+)' : r'\1 \2'}


 def replace():
     global text
     final_text = ''
     for i in dic:
         new_text = re.sub(str(i), str(dic[i]), text)
         text = new_text
     return text

 print (replace())

1 个答案:

答案 0 :(得分:3)

问题是您复制并粘贴了错误。

此模式有效:

'(стат.{0,4}) (\d+)'

这个没有:

'(cтат.{0,4}) (\d+)'

为什么呢?因为在第一个和你的搜索字符串中,第一个字符是U + 0441,一个西里尔字母小Es。但是在第二个中,它是一个U + 0063,一个拉丁语小C.当然,这两个在大多数字体中看起来都相同,但它们不是同一个字符。


那么,你怎么知道?好吧,当我怀疑这个问题时,我就是这样做的:

>>> a = '(стат.{0,4}) (\d+)' # copied and pasted from your working code
>>> b = '(cтат.{0,4}) (\d+)' # copied and pasted from your broken code
>>> print(a.encode('unicode-escape').decode('ascii'))
(\u0441\u0442\u0430\u0442.{0,4}) (\\d+)
>>> print(b.encode('unicode-escape').decode('ascii'))
(c\u0442\u0430\u0442.{0,4}) (\\d+)

差别很明显:第一个有一个\u0441转义序列,第二个转义序列有一个纯ASCII c