Converter da string ASCII codificada em hexadecimal para ASCII simples?

146

Como posso converter de hexadecimal para ASCII simples em Python?

Observe que, por exemplo, desejo converter "0x7061756c" para "paul".

Paul Reiners
fonte
Eu tentei um monte de coisas que eu encontrei aqui: docs.python.org/library/binascii.html
Paul Reiners
1
Com a ajuda do link que você acabou de nos fornecer, encontrei a função que você estava procurando. O que exatamente você tentou e por que não funcionou?
22812 Vincent Savard
1
Tentei o seguinte: >>> binascii.b2a_hqx ("0x7061756c") '- (Jh- $ Ba0c8fB`' >>> binascii.b2a_uu ("0x7061756c") "*, '@ W, # 8Q-S4V8P \ n" >>> binascii.b2a_base64 ("0x7061756c") 'MHg3MDYxNzU2Yw == \ n' >>> binascii.b2a_qp ("0x7061756c") '0x7061756c') '0x7061756c' >>> binascii.b2a_hexc "" 0x70617 '' .b2a_hex (0x7061756c) Traceback (última chamada mais recente): Arquivo "<stdin>", linha 1, em <module> TypeError: deve ser uma string ou um buffer, não int >>>
Paul Reiners
Nenhum deles funcionou, porque nenhum deles retornou 'paul'.
Paul Reiners
2
Você não quer dizer ASCII de 7 bits? (O que é meio bobo porque o ASCII é de apenas 7 bits.) Um GUID é de 128 bits ...

Respostas:

231

Uma solução um pouco mais simples:

>>> "7061756c".decode("hex")
'paul'
cjm
fonte
142
não há .decode('hex')no Python 3. .decode('hex')usos binascii.unhexlify()no Python 2 .
JFS
2
Obrigado por apontar isso, não estou tão familiarizado com o Python 3. Essa solução também não funcionará em 1 até onde eu sei.
Cjm 10/03
26
codecs.decode("7061756c", "hex")funciona para Python 2 e Python 3. Mas ele retorna uma bytes()string no Python 3. Mas isso é razoável para uma string ASCII.
Mark Evans
100

Não há necessidade de importar nenhuma biblioteca:

>>> bytearray.fromhex("7061756c").decode()
'paul'
user4369081
fonte
2
A melhor solução para mim (funciona com o python 3), pois até aceita espaços:bytearray.fromhex("70 61 75 6C").decode()
Jona
bytearray.fromhex ("70e4756c"). decode (encoding = "Latin1") 'päul' Para aqueles que jogam em binário, os caracteres estendidos sufocam com a decodificação utf-8 padrão, além disso, esta é a resposta mais portátil Entendo! Obrigado!
Grambo
É claro que você precisa saber a codificação real dos dados para que sejam interpretados como texto. O uso 'latin-1'irá livrar-se de quaisquer erros, mas poderá produzir uma rabiscos completos se o texto não for realmente latino-1.
Tripleee 5/10/19
43
>>> txt = '7061756c'
>>> ''.join([chr(int(''.join(c), 16)) for c in zip(txt[0::2],txt[1::2])])
'paul'                                                                          

estou apenas me divertindo, mas as partes importantes são:

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

vai olhar para binascii agora ...

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

legal (e eu não tenho idéia do por que outras pessoas querem fazer você pular em círculos antes que elas ajudem).

andrew cooke
fonte
16

No Python 2:

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

No Python 3:

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

Aqui está minha solução ao trabalhar com números inteiros hexadecimais e não cadeias hexadecimais:

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
fonte
+1 para um exemplo útil, mas você não está convertendo "hex" como entrada, mas está convertendo qualquer número inteiro em uma sequência hexadecimal. Seu código funcionará igualmente bem com print convert_hex_to_ascii(123456).
precisa saber é o seguinte
5

Como alternativa, você também pode fazer isso ...

Intérprete Python 2

print "\x70 \x61 \x75 \x6c"

Exemplo

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:~# 

ou

One-Liner para Python 2

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

Exemplo

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

Intérprete Python 3

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

One-Liner para Python 3

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

Exemplo

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

user@linux:~$ python -c 'print("\x70\x61\x75\x6c")'
paul
Sabrina
fonte
2
Isso funciona bem sem os espaços também e funciona bem em python3 com print ().
Rjferguson
Sim, coloquei de propósito para facilitar a visualização. Deixe-me atualizar a resposta com o Python 3 também.
Sabrina
3

Testado no Python 3.3.2 Há muitas maneiras de conseguir isso, eis uma das mais curtas, usando apenas o material fornecido pelo python:

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

Obviamente, se você não deseja importar nada, sempre pode escrever seu próprio código. Algo muito básico assim:

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
fonte
1
b''.fromhex('7061756c')

use-o sem delimitador

Husky
fonte