Konwertować z ciągu ASCII zakodowanego w formacie Hex na zwykły ASCII?

146

Jak mogę przekonwertować szesnastkowy na zwykły ASCII w Pythonie?

Zauważ, że na przykład chcę przekonwertować „0x7061756c” na „paul”.

Paul Reiners
źródło
Wypróbowałem kilka rzeczy, które znalazłem tutaj: docs.python.org/library/binascii.html
Paul Reiners
1
Z pomocą linku, który nam podałeś, znalazłem funkcję, której szukałeś. Co dokładnie próbowałeś i dlaczego nie zadziałało?
Vincent Savard,
1
Wypróbowałem następujące: >>> 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 ("0x7061736i") .b2a_hex (0x7061756c) Traceback (ostatnie wywołanie ostatnie): Plik „<stdin>”, wiersz 1, w <module> TypeError: musi być ciągiem znaków lub buforem, a nie int >>>
Paul Reiners
Żaden z nich nie pracował, bo żaden z nich nie wrócił „Paul”.
Paul Reiners,
2
Czy nie masz na myśli „7-bitowego” ASCII? (Co jest trochę głupie, ponieważ ASCII ma tylko 7 bitów.) Identyfikator GUID ma 128 bitów ...

Odpowiedzi:

231

Nieco prostsze rozwiązanie:

>>> "7061756c".decode("hex")
'paul'
cjm
źródło
142
nie ma .decode('hex')w Pythonie 3. .decode('hex')zastosowań binascii.unhexlify()w Pythonie 2 .
jfs
2
Dzięki za zwrócenie uwagi, nie znam Pythona 3. To rozwiązanie również nie będzie działać w 1, o ile wiem.
cjm
26
codecs.decode("7061756c", "hex")działa dla Pythona 2 i Pythona 3. Ale zwraca bytes()łańcuch w Pythonie 3. Ale jest to rozsądne dla łańcucha ASCII.
Mark Evans,
100

Nie ma potrzeby importowania żadnej biblioteki:

>>> bytearray.fromhex("7061756c").decode()
'paul'
user4369081
źródło
2
Najlepsze rozwiązanie dla mnie (działa z Pythonem 3), ponieważ akceptuje nawet spacje:bytearray.fromhex("70 61 75 6C").decode()
Jona,
bytearray.fromhex ("70e4756c"). decode (encoding = "Latin1") 'päul' Dla tych z nas, którzy grają w formacie binarnym, rozszerzone znaki dławią się przy domyślnym dekodowaniu utf-8, poza tym jest to najbardziej przenośna odpowiedź Widzę! Dzięki!
grambo
Oczywiście musisz znać faktyczne kodowanie danych, jeśli mają być interpretowane jako tekst. Użycie 'latin-1'pozbędzie się wszelkich błędów, ale może spowodować kompletny bełkot, jeśli tekst nie jest w rzeczywistości Latin-1.
tripleee
43
>>> txt = '7061756c'
>>> ''.join([chr(int(''.join(c), 16)) for c in zip(txt[0::2],txt[1::2])])
'paul'                                                                          

Po prostu dobrze się bawię, ale najważniejsze części to:

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

spojrzy teraz na binascii ...

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

fajnie (i nie mam pojęcia, dlaczego inni chcą cię zmusić do skakania przez obręcze, zanim pomogą).

Andrew Cooke
źródło
16

W Pythonie 2:

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

W Pythonie 3:

>>> bytes.fromhex('7061756c').decode('utf-8')
'paul'
Julien
źródło
5

Oto moje rozwiązanie podczas pracy z liczbami szesnastkowymi, a nie ciągami szesnastkowymi:

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
źródło
+1 na użyteczny przykład, ale nie konwertujesz „hex” jako wejścia, ale konwertujesz dowolną liczbę całkowitą na ciąg szesnastkowy. Twój kod będzie działał równie dobrze z print convert_hex_to_ascii(123456).
Mark Lakata
5

Alternatywnie możesz też zrobić to ...

Python 2 Interpreter

print "\x70 \x61 \x75 \x6c"

Przykład

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

lub

Python 2 One-Liner

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

Przykład

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

Python 3 Interpreter

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

Przykład

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

user@linux:~$ python -c 'print("\x70\x61\x75\x6c")'
paul
Sabrina
źródło
2
Działa to dobrze również bez spacji i działa dobrze w python3 z print ().
rjferguson
Tak, umieściłem to celowo, żeby było lepiej widoczne. Pozwólcie, że zaktualizuję odpowiedź również w Pythonie 3.
Sabrina
3

Przetestowane w Pythonie 3.3.2 Jest wiele sposobów, aby to osiągnąć, oto jeden z najkrótszych, wykorzystujący wyłącznie elementy dostarczane przez Pythona:

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

Oczywiście, jeśli nie chcesz niczego importować, zawsze możesz napisać własny kod. Coś bardzo podstawowego, takiego:

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
źródło
1
b''.fromhex('7061756c')

używaj go bez ogranicznika

Ochrypły
źródło