2010-11-02 5 views
3

j'ai une chaîne qui contient une valeur flottante en caractères hexadécimaux comme ceci:Déballez chaîne avec hexadécimaux

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

Je veux extraire le flotteur, mais pour le faire que je dois faire Python voir la chaîne comme 4 caractères hexadécimaux, au lieu de 16 caractères réguliers. D'abord, j'essayé de remplacer les barres obliques vers l'avant, mais je suis une erreur:

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

J'ai découvert

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

fait exactement ce que je veux, mais comment puis-je convertir la chaîne?

Répondre

6

Chaque fois que je vois une chaîne (malformé), comme un composé de cette liste de caractères:

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

quand ce qui était prévu était cette liste de caractères

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

Je tends la decode('string_escape') méthode. Mais pour l'utiliser, nous devons remplacer les deux caractères r'\\' par r'\x'. Pour l'utiliser, nous devons remplacer les deux caractères r'\\' par r'\x'. Vous pouvez utiliser la méthode replace(...) pour cela.

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. Cette utilisation de la méthode decode fonctionne dans Python2 mais ne fonctionnera pas dans Python3. En Python3 codecs.decode est strictement destiné à convertir des objets octets en objets chaîne (err, ce que Python2 appelle les objets unicode), alors que dans l'exemple ci-dessus, decode convertit réellement un objet chaîne en un objet chaîne. La plupart des codecs de décodage dans Python2 convertissent des objets string en objets unicode, mais pas un peu comme 'string_escape'. En général, ils ont été déplacés vers d'autres modules, ou appelés d'une autre manière. En Python3, l'équivalent de hexstring.decode('string_encode') est codecs.escape_decode(hexstring)[0].

Edit: Une autre façon, dans le même esprit à la réponse de jsbueno, est d'utiliser 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' 

Ces timeit résultats suggèrent binascii.unhexlify est le plus rapide:

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 

Modifier, par les commentaires:

This answer contains raw strings. The Department of Public Health advises that eating raw or undercooked strings poses a health risk to everyone, but especially to the elderly, young children under age 4, pregnant women and other highly susceptible individuals with compromised immune systems. Thorough cooking of raw strings reduces the risk of illness.

+1

Vous devriez souligner que l'affaire implique ici des chaînes premières. – detly

+0

@detly: Je suis désolé, mais je ne comprends pas. Bien que j'utilise des chaînes brutes pour la commodité de la notation, l'astuce ne dépend pas vraiment de la notation. Je pourrais réécrire les morceaux de code sans aucune utilisation de chaînes brutes. – unutbu

+0

@detly: Oh ... peut-être que vous voulez dire que l'OP a dit "\\ 64 \\ 2e \\ 9b \\ 38" 'alors que j'ai commencé avec' r "\\ 64 \\ 2e \\ 9b \\ 38 "'.Je devine que l'OP signifiait vraiment "r" \\ 64 \\ 2e \\ 9b \\ 38 "', parce que plus tard dans le texte il mentionne qu'il est de 16 caractères, alors que 'len (" \\ 64 \ \ 2e \\ 9b \\ 38 ")' est seulement 12. – unutbu

0

Un chemin plus court pour aller ehr e, est de simplement se débarrasser des « \ » caractères et faire python voir chacun deux chiffres hexadécimaux comme un octet, en utilisant le « hex_codec »:

struct.unpack("f", "\\64\\2e\\9b\\38".replace("\\", "\").decode("hex_codec")) 
Questions connexes