如何使用正则表达式在Python字符串中删除十六进制值?

3
我有一个matlab中的单元数组。
columns = {'MagX', 'MagY', 'MagZ', ...
           'AccelerationX',  'AccelerationX',  'AccelerationX', ...
           'AngularRateX', 'AngularRateX', 'AngularRateX', ...
           'Temperature'}

我使用这些脚本,利用matlab的hdf5write函数将数组保存为hdf5格式。
然后我使用pytables将hdf5文件读入python。单元格数组以字符串的numpy数组的形式出现。我将其转换为列表,以下是输出结果:
>>>columns
['MagX\x00\x00\x00\x08\x01\x008\xe6\x7f',
 'MagY\x00\x7f\x00\x00\x00\xee\x0b9\xe6\x7f',
 'MagZ\x00\x00\x00\x00\x001',
 'AccelerationX',
 'AccelerationY',
 'AccelerationZ',
 'AngularRateX',
 'AngularRateY',
 'AngularRateZ',
 'Temperature']

这些十六进制值似乎从某处插入了字符串中,我想要将它们移除。它们并不总是出现在列表的前三个项目中,我需要一个好的方法来处理它们或找出它们为什么会首次出现在那里。
>>>print columns[0]
Mag8�
>>>columns[0]
'MagX\x00\x00\x00\x08\x01\x008\xe6\x7f'
>>>repr(columns[0])
"'MagX\\x00\\x00\\x00\\x08\\x01\\x008\\xe6\\x7f'"
>>>print repr(columns[0])
'MagX\x00\x00\x00\x08\x01\x008\xe6\x7f'

我尝试使用正则表达式来去除十六进制值,但是效果不佳。

>>>re.sub('(\w*)\\\\x.*', '\1', columns[0])
'MagX\x00\x00\x00\x08\x01\x008\xe6\x7f'
>>>re.sub('(\w*)\\\\x.*', r'\1', columns[0])
'MagX\x00\x00\x00\x08\x01\x008\xe6\x7f'
>>>re.sub(r'(\w*)\\x.*', '\1', columns[0])
'MagX\x00\x00\x00\x08\x01\x008\xe6\x7f'
>>>re.sub('([A-Za-z]*)\x00', r'\1', columns[0])
'MagX\x08\x018\xe6\x7f'
>>>re.sub('(\w*?)', '\1', columns[0])
'\x01M\x01a\x01g\x01X\x01\x00\x01\x00\x01\x00\x01\x08\x01\x01\x01\x00\x018\x01\xe6\x01\x7f\x01'

有没有关于如何处理这个问题的建议?
3个回答

9
您可以通过以下方式删除所有非单词字符:
>>> re.sub(r'[^\w]', '', 'MagX\x00\x00\x00\x08\x01\x008\xe6\x7f')
'MagX8'

正则表达式[^\w]将匹配任何不是字母、数字或下划线的字符。通过在re.sub中提供该正则表达式并用空字符串替换,您可以删除字符串中的所有其他字符。
由于可能还有其他字符需要保留,更好的解决方案可能是指定一个更大的字符范围,以保留不包括控制字符在内的字符。例如:
>>> re.sub(r'[^\x20-\x7e]', '', 'MagX\x00\x00\x00\x08\x01\x008\xe6\x7f')
'MagX8'

或者,您可以将[^\x20-\x7e]替换为等效的[^ -~],具体取决于哪个更清晰易懂。

要排除此第一个控制字符后的所有字符,请添加.*,如下所示:

>>> re.sub(r'[^ -~].*', '', 'MagX\x00\x00\x00\x08\x01\x008\xe6\x7f')
'MagX'

谢谢,这很简单并且正好满足我的需求。^ 字符是我经常忘记使用的东西。 - moorepants

1

它们实际上不在字符串中:您有未转义的控制字符,Python使用十六进制表示法显示它们 - 这就是为什么在打印该值时会看到一个不寻常的符号。

您应该能够简单地删除正则表达式中的额外引用级别,但您也可以仅依赖于类似于regexp模块的通用空格类,它将匹配除制表符和空格之外的空格字符:

>>> import re
>>> re.sub(r'\s', '?', "foo\x00bar")
'foo\x00bar'
>>> print re.sub(r'\s', '?', "foo\x00bar")
foobar

我经常使用这个函数来替换所有输入的空格,包括不间断空格字符,只保留一个空格:

>>> re.sub(r'[\xa0\s]+', ' ', input_str)

你知道有哪些参考资料可以解释未转义和已转义的控制字符吗? - moorepants
这其实就是标准的Python字符串行为:字符串可以包含二进制值,当终端显示内容时,它可以自由解释(这就是为什么意外显示二进制数据可能会导致字体变化或系统响铃声的原因)。既然这没有什么帮助,而且有点烦人,交互式Python shell将会显示一个字符串的表示形式(例如repr(foo)返回的内容),其中包括您在Python源代码中正确输入该字符串所需的转义。 - Chris Adams

0

您也可以在不导入re的情况下完成此操作。例如,如果您只想保留ASCII字符:

good_string = ''.join(c if ord(c) < 129 else '?' for c in bad_string)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接