如何用正则表达式可移植地解析(Unicode)度符号?

15 投票
1 回答
7332 浏览
提问于 2025-04-17 10:45

我正在为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())

这会产生错误的结果: 'В°' 而不是 °

所以在某些情况下,你需要知道输入数据的编码。

撰写回答