如何使用正则表达式可移植地解析(Unicode)度数符号?
Posted
技术标签:
【中文标题】如何使用正则表达式可移植地解析(Unicode)度数符号?【英文标题】:How to portably parse the (Unicode) degree symbol with regular expressions? 【发布时间】:2012-02-15 16:03:21 【问题描述】:我正在为 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 的表示方式与我的不同的系统上,代码会中断吗?如果是这样,我怎样才能让它便携?
【问题讨论】:
带有re.UNICODE
标志,RE 与\W\WC
或\WC
都不匹配。或者,我误会你了吗?
还有“℃
”,它是一个单个字符,表示摄氏度。非常感谢 Unicode 联盟!
【参考方案1】:
可能的便携式解决方案:
将输入数据转换为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 已经在 cmets 中指出了这一点。
更新
J.F. Sebastiancmets 关于输入编码的说明:
check_output()
返回的二进制数据有时可以是文本(在这种情况下应该具有已知的字符编码,您可以将其转换为 Unicode)。无论如何 ord(u'°') == 176 所以它不能使用 ASCII 编码进行编码。
因此,要将输入数据解码为unicode
,基本上*您应该使用来自系统语言环境的编码,使用locale.getpreferredencoding()
,例如:
data = subprocess.check_output(...).decode(locale.getpreferredencoding())
正确编码的数据:
在这种情况下,如果没有 re.UNICODE,您将获得相同的输出。
为什么?因为在俄语 Win7 上,cp1251
为 preferredencoding
,如果我们有例如 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())
会产生错误的结果:'В°'
而不是°
。
因此,在某些情况下,您需要了解输入数据的编码。
【讨论】:
当然,但是为这类事情提供一个完整的工作示例总是一个好主意。即使有完整的设施,对于许多程序员来说,正确处理 Unicode 也很困难:( +1:用于“将输入数据转换为 unicode”。顺便说一句,在这种情况下,如果没有re.UNICODE
,您将获得相同的输出。
谢谢。我玩过它。在“真实”代码中,数据实际上来自对subprocess.check_output
的调用的输出,该调用将其数据返回为 ASCII,而不是 Unicode,因此这在此处不太适用。也许更明智的做法是迁移到“一切”都是 Unicode 的 Python3?嗯。
@snim2: check_output()
返回二进制数据,有时可以是文本(that should have a known character encoding in this case,您可以将其转换为Unicode)。无论如何ord(u'°') == 176
所以它不能使用ASCII 编码进行编码。 Python 3 无法帮助您,因为 check_output
可以返回没有意义的文本数据,例如二进制图像数据(您无法将其转换为 Unicode;没有关联的字符编码)。
@reclosedev:你的意思可能是locale.getpreferredencoding()
。它完全独立于用于脚本的源编码。以上是关于如何使用正则表达式可移植地解析(Unicode)度数符号?的主要内容,如果未能解决你的问题,请参考以下文章
使用 CountVectorizer 的无空格 unicode 句子的正则表达式