Распаковать строку с шестнадцатеричными числами - PullRequest
3 голосов
/ 02 ноября 2010

У меня есть строка, которая содержит значение с плавающей точкой в ​​шестнадцатеричных символах, например:

"\\64\\2e\\9b\\38"

Я хочу извлечь число с плавающей точкой, но для этого я должен заставить Python видеть строку как 4шестнадцатеричные символы вместо 16 обычных символов.Сначала я попытался заменить косую черту, но получил ошибку:

>>>> hexstring.replace("\\", "\x")
ValueError: invalid \x escape

Я обнаружил, что

struct.unpack("f", "\x64\x2e\x9b\x38") 

делает именно то, что я хочу, но как преобразовать строку?

Ответы [ 2 ]

6 голосов
/ 02 ноября 2010

Всякий раз, когда я вижу (искаженную) строку, например, строку, составленную из этого списка символов:

['\\', '\\', '6', '4', '\\', '\\', '2', 'e', '\\', '\\', '9', 'b', '\\', '\\', '3', '8']

когда предназначался этот список символов

['\x64', '\x2e', '\x9b', '\x38']

Я достигаю метода decode('string_escape').

Но чтобы использовать его, нам нужно заменить два символа r'\\' на r'\x'. Для этого вы можете использовать метод replace(...).

In [37]: hexstring=r'\\64\\2e\\9b\\38'

In [38]: struct.unpack('f',(hexstring.replace(r'\\',r'\x').decode('string_escape')))
Out[38]: (7.3996168794110417e-05,)

In [39]: struct.unpack("f", "\x64\x2e\x9b\x38")
Out[39]: (7.3996168794110417e-05,)

PS. Такое использование метода decode работает в Python2, но не будет работать в Python3. В Python3 codecs.decode предназначен исключительно для преобразования байтовых объектов в строковые объекты (ошибочно, то, что Python2 называет объектами юникода), тогда как в приведенном выше примере decode фактически преобразовывает строковый объект в строковый объект. Большинство кодеков декодирования в Python2 действительно преобразуют строковые объекты в объекты Unicode, но некоторые, такие как 'string_escape', не делают. Как правило, они были перемещены в другие модули или вызваны каким-либо другим способом.

В Python3 эквивалент hexstring.decode('string_encode') равен codecs.escape_decode(hexstring)[0].

Редактировать: Другой способ, похожий по духу на ответ jsbueno, заключается в использовании binascii.unhexlify:

In [76]: import binascii
In [81]: hexstring=r"\\64\\2e\\9b\\38"
In [82]: hexstring.replace('\\','')
Out[82]: '642e9b38'

In [83]: binascii.unhexlify(hexstring.replace('\\',''))
Out[83]: 'd.\x9b8'

Эти timeit результаты предполагают, что binascii.unhexlify является самым быстрым:

In [84]: %timeit binascii.unhexlify(hexstring.replace('\\',''))
1000000 loops, best of 3: 1.42 us per loop

In [85]: %timeit hexstring.replace('\\','').decode('hex_codec')
100000 loops, best of 3: 2.94 us per loop

In [86]: %timeit hexstring.replace(r'\\',r'\x').decode('string_escape')
100000 loops, best of 3: 2.13 us per loop

Редактировать, по комментариям:

Этот ответ содержит необработанные строки. Департамент общественного здравоохранения консультирует что есть сырые или недоваренные строки представляет опасность для здоровья для всех, но особенно пожилым, молодым дети до 4 лет, беременные женщины и другие очень восприимчивые лица с ослабленным иммунитетом системы. Тщательное приготовление сырья Струны снижает риск заболевания.

0 голосов
/ 02 ноября 2010

Более короткий путь - просто избавиться от символов "\" и заставить python рассматривать каждые две шестнадцатеричные цифры как байт, используя "hex_codec":

struct.unpack("f", "\\64\\2e\\9b\\38".replace("\\", "\").decode("hex_codec"))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...