Преобразовать из строки ASCII, закодированной в шестнадцатеричном формате, в обычный ASCII?

147

Как я могу преобразовать из шестнадцатеричного в простой ASCII в Python?

Обратите внимание, что, например, я хочу преобразовать «0x7061756c» в «paul».

Пол Райнерс
источник
Я попробовал кучу вещей, которые нашел здесь: docs.python.org/library/binascii.html
Пол Рейнерс
1
С помощью ссылки, которую вы только что дали нам, я нашел функцию, которую вы искали. Что именно вы пробовали и почему это не сработало?
Винсент Савард
1
Я попробовал следующее: >>> 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' >>> binascii.b2a_hex ("0x706175363636373663)) .b2a_hex (0x7061756c) Traceback (последний вызов был последним): файл "<stdin>", строка 1, в <module> TypeError: должен быть строкой или буфером, а не int >>>
Пол Рейнерс
Никто из них не работал, потому что никто из них не возвратил «Пол».
Пол Райнерс
2
Разве вы не имеете в виду "7-битный" ASCII? (Это глупо, потому что ASCII только 7-битный.) GUID 128-битный ...

Ответы:

231

Немного более простое решение:

>>> "7061756c".decode("hex")
'paul'
CJM
источник
143
нет .decode('hex')на Python 3. .decode('hex')использует binascii.unhexlify()на Python 2 .
Jfs
2
Спасибо за указание на это, я не настолько знаком с Python 3. Это решение также не будет работать в 1, насколько я знаю.
CJM
27
codecs.decode("7061756c", "hex")работает для Python 2 и Python 3. Но он возвращает bytes()строку в Python 3. Но это разумно для строки ASCII.
Марк Эванс
101

Нет необходимости импортировать любую библиотеку:

>>> bytearray.fromhex("7061756c").decode()
'paul'
user4369081
источник
2
Лучшее решение для меня (работает с python 3), так как оно принимает пробелы:bytearray.fromhex("70 61 75 6C").decode()
Jona
bytearray.fromhex ("70e4756c"). decode (encoding = "Latin1") 'päul' Для тех из нас, кто играет в двоичном формате, расширенные символы заглушают декодирование utf-8 по умолчанию, кроме этого, это самый переносимый ответ Я вижу! Спасибо!
Грамбо
Конечно, вы должны знать фактическую кодировку данных, если они должны интерпретироваться как текст. Использование 'latin-1'избавит от любых ошибок, но может привести к полной тарабарщине, если текст на самом деле не Latin-1.
tripleee
43
>>> txt = '7061756c'
>>> ''.join([chr(int(''.join(c), 16)) for c in zip(txt[0::2],txt[1::2])])
'paul'                                                                          

Мне просто весело, но важными частями являются:

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

сейчас посмотрим на бинаскии ...

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

круто (и я понятия не имею, почему другие люди хотят заставить вас прыгать через обручи, прежде чем они помогут).

Эндрю Кук
источник
16

В Python 2:

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

В Python 3:

>>> bytes.fromhex('7061756c').decode('utf-8')
'paul'
Julien
источник
5

Вот мое решение при работе с шестнадцатеричными целыми числами, а не шестнадцатеричными строками:

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
источник
+1 для полезного примера, но вы не конвертируете «hex» в качестве входных данных, но вы конвертируете любое целое число в шестнадцатеричную строку. Ваш код будет работать одинаково хорошо print convert_hex_to_ascii(123456).
Марк Лаката
5

Кроме того, вы также можете сделать это ...

Python 2 переводчик

print "\x70 \x61 \x75 \x6c"

пример

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

или

Python 2 One-Liner

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

пример

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

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

Python 3 One-Liner

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

пример

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

user@linux:~$ python -c 'print("\x70\x61\x75\x6c")'
paul
Sabrina
источник
2
Это прекрасно работает и без пробелов, и отлично работает в python3 с print ().
rjferguson
Да, я ставлю это специально, чтобы было легче видеть. Позвольте мне обновить ответ и с Python 3.
Сабрина
3

Протестировано в Python 3.3.2 Есть много способов сделать это, вот один из самых коротких, используя только предоставленные Python вещи:

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

Конечно, если вы не хотите ничего импортировать, вы всегда можете написать свой собственный код. Нечто очень простое, как это:

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)
Виктор Баррантес
источник
1
b''.fromhex('7061756c')

используйте его без разделителя

хриплый
источник