如何用正则表达式可移植地解析(Unicode)度符号?
我正在为Ubuntu上的sensors
工具的输出写一个简单的正则表达式解析器。这里有一行我正在解析的文本示例:
temp1: +31.0°C (crit = +107.0°C)
这是我用来匹配该文本的正则表达式(用Python写的):
temp_re = re.compile(r'(temp1:)\s+(\+|-)(\d+\.\d+)\W\WC\s+'
r'\(crit\s+=\s+(\+|-)(\d+\.\d+)\W\WC\).*')
这段代码按预期工作,可以匹配我上面给出的示例文本。我真正感兴趣的部分就是数字,所以这部分:
(\+|-)(\d+\.\d+)\W\WC
它是从匹配+
或-
符号开始,最后匹配°C
。
我想问的是,为什么要用两个\W
(非字母数字字符)来匹配°
而不是一个?如果我的代码在其他系统上表现不同,Unicode的表示方式也不一样,那会不会出错?如果会的话,我该怎么做才能让它更通用呢?
1 个回答
8
可能的便携解决方案:
把输入的数据转换成unicode格式,然后在正则表达式中使用 re.UNICODE
这个标志。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re
data = u'temp1: +31.0°C (crit = +107.0°C)'
temp_re = re.compile(ur'(temp1:)\s+(\+|-)(\d+\.\d+)°C\s+'
ur'\(crit\s+=\s+(\+|-)(\d+\.\d+)°C\).*', flags=re.UNICODE)
print temp_re.findall(data)
输出结果
[(u'temp1:', u'+', u'31.0', u'+', u'107.0')]
编辑
@netvope 在问题的评论中已经提到过这个。
更新
来自 J.F. Sebastian 的评论关于输入编码的说明:
check_output()
返回的是二进制数据,有时候这些数据可以是文本(在这种情况下应该有已知的字符编码,你可以把它转换成Unicode)。总之,ord(u'°') 等于176,所以它不能用ASCII编码。
所以,要把输入数据解码成 unicode
,基本上你应该使用系统区域设置中的编码,方法是用 locale.getpreferredencoding()
,例如:
data = subprocess.check_output(...).decode(locale.getpreferredencoding())
如果数据编码正确:
在这种情况下,你会得到相同的输出,不需要使用 re.UNICODE。
为什么说基本上呢?因为在使用 cp1251
作为 preferredencoding
的俄罗斯Win7上,如果我们有一个 script.py
,它把输出解码成 utf-8
:
#!/usr/bin/env python
# -*- coding: utf8 -*-
print u'temp1: +31.0°C (crit = +107.0°C)'.encode('utf-8')
而我们需要解析它的输出:
subprocess.check_output(['python',
'script.py']).decode(locale.getpreferredencoding())
这会产生错误的结果: 'В°'
而不是 °
。
所以在某些情况下,你需要知道输入数据的编码。