有人可以解释一下正则表达式的这种行为:
当我用一些其他Unicode字符替换Unicode字符串的最后两个字符时,它在字符串末尾的行边界($
)下工作正常但如果我指定{{1}则会产生意外结果方括号$
。
字边界[$]
也会产生意想不到的结果,令人惊讶\b
与\B
匹配的内容相匹配。
\b
答案 0 :(得分:1)
re.sub
的签名是:
sub(pattern, repl, string, count=0, flags=0)
re.U
标志正传递给count
,因此re.U
标志不执行任何操作。确保使用关键字参数,如:
re.sub(ur'\u06cc\u0670\b', u'\u0627', line, flags=re.U)
# ^~~~~~
[…]
定义了一个字符类,$
在括号内并不特殊。因此[$]
只会匹配一个字面的美元符号。
\b
匹配单词(“\ w”)和非单词(“\ W”,或字符串的开头/结尾)之间的边界,\B
匹配任何地方那不是\b
。现在,\u0670
是Unicode中的非单词:
>>> re.findall(ur'\w', line, flags=re.U)
[u'\u0627', u'\u062f', u'\u0646', u'\u06cc']
>>> re.findall(ur'\W', line, flags=re.U)
[u'\u0670']
这意味着\u0670
之后的字符串结尾不是字边界,因为\u0670
不是单词。因此\b
无法与之匹配,这意味着\B
将与之匹配。
Unicode中\w
的含义是“[0-9_]
加上Unicode字符属性数据库中的classified as alphanumeric”。
像U + 06CC(阿拉伯字母波斯语)这样的字符被归类为字母,其他(Lo)所以它是一个单词,但是U + 0670(阿拉伯字母Superscript Alef)被归类为< strong> Mark,Nonspacing(Mn)因此
(您可以在https://docs.python.org/2/library/re.html)
中查看Python正则表达式语法的详细信息对于以下评论,您可以使用negative look-ahead代替小组:
re.sub(ur'(?:[\u06cc\u06d2]\u0670|\u0670[\u06cc\u06d2])(?!\w)', u'\u0627', line, flags=re.U)
下面,
[\u06cc\u06d2]\u0670|\u0670[\u06cc\u06d2]
与您的\u06cc\u0670|\u06d2\u0670|\u0670\u06cc|\u0670\u06d2
相同,但类似的案例组合在一起(?:…)
定义non-capturing group,以便您可以从更改中提取所需的“\ b”(?!\w)
表示只有在下一个字符不是单词时才匹配。 结果如下:
>>> re.sub(u'(?:[\u06cc\u06d2]\u0670|\u0670[\u06cc\u06d2])(?!\w)', u'\u0627', line, flags=re.U)
u'\u0627\u062f\u0646\u0627'
>>> re.sub(u'(?:[\u06cc\u06d2]\u0670|\u0670[\u06cc\u06d2])(?!\w)', u'\u0627', line + u'\u0646', flags=re.U)
u'\u0627\u062f\u0646\u06cc\u0670\u0646'
>>> re.sub(u'(?:[\u06cc\u06d2]\u0670|\u0670[\u06cc\u06d2])(?!\w)', u'\u0627', line + u'\u061f', flags=re.U)
u'\u0627\u062f\u0646\u0627\u061f'