¿Convertir de cadena ASCII codificada en hexadecimal a ASCII simple?

147

¿Cómo puedo convertir de hexadecimal a ASCII simple en Python?

Tenga en cuenta que, por ejemplo, quiero convertir "0x7061756c" a "Paul".

Paul Reiners
fuente
He probado un montón de cosas que encontré aquí: docs.python.org/library/binascii.html
Paul Reiners
1
Con la ayuda del enlace que nos acaba de dar, encontré la función que estaba buscando. ¿Qué probaste exactamente y por qué no funcionó?
Vincent Savard
1
Intenté lo siguiente: >>> binascii.b2a_hqx ("0x7061756c") '- (Jh- $ Ba0c8fB`' >>> binascii.b2a_uu ("0x7061756c") "*, '@ W, # 8Q-S4V8P \ n" >>> binascii. .b2a_hex (0x7061756c) Traceback (última llamada más reciente): Archivo "<stdin>", línea 1, en <module> TypeError: debe ser string o buffer, no int >>>
Paul Reiners
Ninguno de ellos trabajó, porque ninguno de ellos regresó 'Paul'.
Paul Reiners
2
¿No quieres decir ASCII de "7 bits"? (Lo cual es un poco tonto porque ASCII tiene solo 7 bits). Un GUID es de 128 bits ...

Respuestas:

231

Una solución un poco más simple:

>>> "7061756c".decode("hex")
'paul'
cjm
fuente
143
no hay .decode('hex')en Python 3. .decode('hex')usos binascii.unhexlify()en Python 2 .
jfs
2
Gracias por señalarlo, no estoy tan familiarizado con Python 3. Esta solución tampoco funcionará en 1 hasta donde yo sé.
cjm
27
codecs.decode("7061756c", "hex")funciona para Python 2 y Python 3. Pero devuelve una bytes()cadena en Python 3. Pero eso es razonable para una cadena ASCII.
Mark Evans
101

No es necesario importar ninguna biblioteca:

>>> bytearray.fromhex("7061756c").decode()
'paul'
user4369081
fuente
2
La mejor solución para mí (funciona con Python 3) ya que incluso acepta espacios:bytearray.fromhex("70 61 75 6C").decode()
Jona
bytearray.fromhex ("70e4756c"). decode (encoding = "Latin1") 'päul' Para aquellos de nosotros que jugamos en binario, los caracteres extendidos se ahogan en la decodificación utf-8 predeterminada, aparte de eso, esta es la respuesta más portátil ¡Veo! ¡Gracias!
grambo
Por supuesto, debe conocer la codificación real de los datos si debe interpretarse como texto. El uso 'latin-1'eliminará cualquier error, pero puede producir un galimatías completo si el texto no es realmente latino-1.
tripleee
43
>>> txt = '7061756c'
>>> ''.join([chr(int(''.join(c), 16)) for c in zip(txt[0::2],txt[1::2])])
'paul'                                                                          

Me estoy divirtiendo, pero las partes importantes son:

>>> int('0a',16)         # parse hex
10
>>> ''.join(['a', 'b'])  # join characters
'ab'
>>> 'abcd'[0::2]         # alternates
'ac'
>>> zip('abc', '123')    # pair up
[('a', '1'), ('b', '2'), ('c', '3')]        
>>> chr(32)              # ascii to character
' '

mirará a binascii ahora ...

>>> print binascii.unhexlify('7061756c')
paul

genial (y no tengo idea de por qué otras personas quieren hacerte saltar a través de los aros antes de que ayuden).

Andrew Cooke
fuente
16

En Python 2:

>>> "7061756c".decode("hex")
'paul'

En Python 3:

>>> bytes.fromhex('7061756c').decode('utf-8')
'paul'
Julien
fuente
5

Aquí está mi solución cuando trabajo con enteros hexadecimales y no con cadenas hexadecimales:

def convert_hex_to_ascii(h):
    chars_in_reverse = []
    while h != 0x0:
        chars_in_reverse.append(chr(h & 0xFF))
        h = h >> 8

    chars_in_reverse.reverse()
    return ''.join(chars_in_reverse)

print convert_hex_to_ascii(0x7061756c)
carloserivera
fuente
+1 para un ejemplo útil, pero no está convirtiendo "hexadecimal" como entrada, sino que está convirtiendo cualquier número entero en una cadena hexadecimal. Tu código funcionará igual de bien con print convert_hex_to_ascii(123456).
Mark Lakata
5

Alternativamente, también puedes hacer esto ...

Python 2 Intérprete

print "\x70 \x61 \x75 \x6c"

Ejemplo

user@linux:~# python
Python 2.7.14+ (default, Mar 13 2018, 15:23:44) 
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.

>>> print "\x70 \x61 \x75 \x6c"
p a u l
>>> exit()
user@linux:~# 

o

Python 2 One-Liner

python -c 'print "\x70 \x61 \x75 \x6c"'

Ejemplo

user@linux:~# python -c 'print "\x70 \x61 \x75 \x6c"'
p a u l
user@linux:~# 

Python 3 Intérprete

user@linux:~$ python3
Python 3.6.9 (default, Apr 18 2020, 01:56:04) 
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

>>> print("\x70 \x61 \x75 \x6c")
p a u l

>>> print("\x70\x61\x75\x6c")
paul

Python 3 One-Liner

python -c 'print("\x70 \x61 \x75 \x6c")'

Ejemplo

user@linux:~$ python -c 'print("\x70 \x61 \x75 \x6c")'
p a u l

user@linux:~$ python -c 'print("\x70\x61\x75\x6c")'
paul
Sabrina
fuente
2
Esto funciona bien sin los espacios también, y funciona bien en python3 con print ().
rjferguson
Sí, lo puse a propósito para que sea más fácil de ver. Permítanme actualizar la respuesta con Python 3 también.
Sabrina
3

Probado en Python 3.3.2 Hay muchas maneras de lograr esto, esta es una de las más cortas, usando solo cosas proporcionadas por Python:

import base64
hex_data ='57696C6C20796F7520636F6E76657274207468697320484558205468696E6720696E746F20415343494920666F72206D653F2E202E202E202E506C656565656173652E2E2E212121'
ascii_string = str(base64.b16decode(hex_data))[2:-1]
print (ascii_string)

Por supuesto, si no desea importar nada, siempre puede escribir su propio código. Algo muy básico como este:

ascii_string = ''
x = 0
y = 2
l = len(hex_data)
while y <= l:
    ascii_string += chr(int(hex_data[x:y], 16))
    x += 2
    y += 2
print (ascii_string)
Victor Barrantes
fuente
1
b''.fromhex('7061756c')

usarlo sin delimitador

Fornido
fuente