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

3 投票
3 回答
22607 浏览
提问于 2025-04-16 13:01

我在matlab中有一个单元数组

columns = {'MagX', 'MagY', 'MagZ', ...
           'AccelerationX',  'AccelerationX',  'AccelerationX', ...
           'AngularRateX', 'AngularRateX', 'AngularRateX', ...
           'Temperature'}

我使用这些脚本,它们利用matlab的hdf5write函数将数组保存为hdf5格式。

然后,我用pytables在python中读取这个hdf5文件。这个单元数组变成了一个字符串的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 个回答

0

你也可以不使用 re 这个库来实现这个功能。例如,如果你只想保留 ASCII 字符的话,可以这样做:

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

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)
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'

撰写回答