Python 正则表达式模块"re"将 unicode 字符与 \u 匹配



我正在尝试识别和替换字符串中的unicode字符,我正在处理这些字符串以制作关键字匹配过滤器。

例如,给定字符串

"Apple iPhone 12 mini A2176 128GBu00a0(PRODUCT) Red!u00a0Perfect condition! Unlocked!"

我希望当我使用resub函数(用空格"代替模式(时的输出是

"Apple iPhone 12 mini A2176 128GB (PRODUCT) Red! Perfect condition! Unlocked!"

所以我去了一个regex构建和测试网站,想出了这个模式

\u[a-z|0-9]{4}

它捕获2个unicode字符串

u00a0 and u00a0

现在,为了将它应用于我的python代码,我首先尝试了这个片段。在这里,我使用findall函数来查看代码是否会返回unicode字符串

import re
strin = "Apple iPhone 12 mini A2176 128GBu00a0(PRODUCT) Red!u00a0Perfect condition! Unlocked!"

print(re.findall('\u[a-z|0-9]{4}', strin))

导致以下错误返回

re.error: incomplete escape u at position 0

然后我尝试在字符串模式前面添加一个"r"。没有出现错误,但没有返回unicode字符串

print(re.findall(r'\u[a-z|0-9]{4}', strin))

输出为空列表[]然后我尝试了同样的2种方法,但只有1个反斜杠

print(re.findall('u[a-z|0-9]{4}', strin))给出SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 0-1: truncated uXXXX escape

print(re.findall(r'u[a-z|0-9]{4}', strin)) gives 
re.error: incomplete escape u at position 0

您在这里有多个误解(所有这些都是常见的常见问题解答(。

re.findall的参数是一个字符串。在Python中,字符串中的反斜杠必须通过加倍来转义。一个更好的解决方案是使用r"..."原始字符串表示法,尤其是对于正则表达式,它通常需要包含实际正则表达式的字面反斜杠。

findall获得的错误消息告诉您字符转义u[不正确,因为[不是十六进制数。(事实上,即使您的正则表达式在语法上没有错误,它也太匹配了;Python中Unicode字符转义的正则表达式应该是\u[0-9a-f]{4},而不是a-z。(

字符u00a0是单个Unicode字形,在字符串中包含单个字符。你不能用这样的正则表达式来匹配它。可以匹配的是例如

re.findall(r'[u0080-uffef]', strin)

它包含一个字符类,覆盖Unicode基本多语言平面中的非ASCII字符范围(包括代理,正确地说,我们应该排除它,但我们不要去问初学者的问题。也许还需要注意的是,BMP之外还有Unicode字符,可以与[U00010000-U0010FFFF]匹配(。

(顺便注意,字符类[a-z|0-9]包括字符类中的文字字符||代表字符类之外的交替,但在[]中,除了初始^-之外的所有字符都只是文字字符。(

但更根本的是,初学者对";我不懂Unicode的东西"是错误的;响应应该是"0";我需要理解这些东西";,而不是";我需要把它去掉";。很少有简单地删除所有Unicode的好例子,而且这种趋势只会把你拖回到Unicode之前的黑暗时代,那时你只能在西方计算机中表示英语文本(而且几乎不能这样(。

这个特定问题的一个更原则的解决方案是将所有空白字符(可能除了制表符(规范化为ASCII空间,并在遇到其他Unicode字符时找出如何处理它们。什么是合理的在很大程度上取决于您的具体应用程序。对于搜索或NLP,规范化或";"压平";所有文本都转换为接近ASCII的子集,但对于许多其他应用程序,您通常需要更细致的内容。

解决了这个问题,试试

Python 3.8.2 (default, May 18 2021, 11:47:11) 
[Clang 12.0.5 (clang-1205.0.22.9)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> strin = "Apple iPhone 12 mini A2176 128GBu00a0(PRODUCT) Red!u00a0Perfect condition! Unlocked!"
>>> import re
>>> re.sub(r's', ' ', strin)
'Apple iPhone 12 mini A2176 128GB (PRODUCT) Red! Perfect condition! Unlocked!'

如果您的目的只是从文本中删除unicode,那么您的工作太辛苦了。你可以用做得很简单

strin.encode('ascii', 'ignore').decode('ascii')

您将字符串编码为ascii并忽略错误,然后再次将其解码为ascii,从而删除所有非ascii字符

最新更新