Bir dize onaltılık bayt olarak yazdırılsın mı?


156

Bu dize var: Hello world !!ve ben Python olarak kullanarak yazdırmak istiyorum 48:65:6c:6c:6f:20:77:6f:72:6c:64:20:21:21.

hex() yalnızca tamsayılar için çalışır.

Nasıl yapılabilir?


Fikir yalnızca 2 basamaklı onaltılık değerler döndürmekse, bu soru bayt dizelerinin (yani Python 2 strveya Python 3 bytestring) kullanımını ifade eder , çünkü 0… 255'te bir karakterin tamsayıya kesin bir dönüşümü yoktur. Bu nedenle, karakter dizeleri (Python 2 unicodeve Python 3 str), bu onaltılık biçimde dönüştürülebilmesi için önce bazı kodlamalar gerektirir. Aaron Hall'un cevabı buna örnektir.
Eric O Lebigot

Yanıtlar:


227

Dizenizi bir int üreticisine dönüştürebilir, her öğe için onaltılık biçimlendirme uygulayabilir ve ayırıcı ile araya ekleyebilirsiniz:

>>> s = "Hello world !!"
>>> ":".join("{:02x}".format(ord(c)) for c in s)
'48:65:6c:6c:6f:20:77:6f:72:6c:64:20:21:21

3
Python3'te, a strhex olarak baskı kavramının gerçekten anlamlı olmadığını unutmayın; Yazdırmak istediğiniz edeceğiz bytes(dönüştürmek onaltılık olarak nesneyi striçin bytesçağırarak .encode()).
mic_e

8
Aslında, bu doğru pt -8 temsilini sağlarken , python3: ":".join("{:02x}".format(ord(c)) for c in 'løl')return içinde geçersiz çıktı üretir . '6c:f8:6c'":".join("{:02x}".format(c) for c in 'løl'.encode())'6c:c3:b8:6c'
mic_e

2
Bu soru ve cevap türü, girişinizin ASCII olmayan karakterler içermediğini varsayar. Girişinizde emoji veya Latin tabanlı olmayan yazma sistemleri gibi şeyler varsa, bunun ":".join("{:04x}".format(ord(c)) for c in s)yerine kullanmak isteyebilirsiniz ( her bir sayının 4 basamaklı olması için sıfır pedi 02xile değiştirmek 04x)
Boris

@mic_e Neden bu? Scapy, gömülü yorumlayıcıda denediğinizde buna referans verir. WARNING: Calling str(pkt) on Python 3 makes no sense!
sherrellbc

157
':'.join(x.encode('hex') for x in 'Hello World!')

3
Bunu python3'te nasıl yapabilirim?
h__

6
@hyh: içindeki her on altı basamaktan sonra h = binascii.hexlify(b"Hello world !!") to get hex string. b":".join(h[i:i+2] for i in range(0, len(h), 2))eklemek ':'için.
jfs

2
Python 3'te çalışmaz.LookupError: 'hex' is not a text encoding; use codecs.encode() to handle arbitrary codecs
Boris

55

Python 2.x için:

':'.join(x.encode('hex') for x in 'Hello World!')

Yukarıdaki kod Python 3.x ile çalışmaz, 3.x için aşağıdaki kod çalışır:

':'.join(hex(ord(x))[2:] for x in 'Hello World!')

1
Ayrıca daha sonra da
python2.x ile

1
Ancak, ikincisinin önde gelen sıfırları doldurmadığını unutmayın: hex (ord ("\ x00")) [2:] "0" ve "\ x00" .encode ("hex") == "00"
Will Daniels

3
Neden bu çözümlerin her ikisi de diğer kullanıcılar tarafından sunulduktan aylar sonra yeni bir yanıt olarak göndermeye karar verdiniz? Eğer nokta sürüm uyumluluğunu açıklığa kavuşturmak olsaydı, mevcut cevaplarda düzenlemeler önermek daha mantıklı olurdu.
Air

2
Başka yerlerde de belirtildiği gibi, ascii'nin ötesine geçtiğinde ve unicode olarak değerlendirildiğinde bu cevap doğru değildir. ':'. join ('løl' içindeki x için hex (ord (x)) [2:] yanlış '6c: f8: 6c' yazdırırken doğru çıkış '6c: c3: b8: 6c' yazar.
mcduffee

23

Bazılarının daha kolay okunabileceği iki satırdaki başka bir yanıttır ve bir dizedeki satır sonları veya diğer garip karakterlerde hata ayıklamaya yardımcı olur:

Python 2.7 için

for character in string:
    print character, character.encode('hex')

Python 3.7 için (3'ün tüm sürümlerinde test edilmemiştir)

for character in string:
    print(character, character.encode('utf-8').hex())

Bu, Python 3.6.8 (en azından) itibariyle işe yaramaz: "hex" bir dize kodlaması değildir. codecs.encode(<bytestring>, "hex")olsa işe yarıyor.
Eric O Lebigot

2
Ah, bilgi için güzel teşekkürler ... evet bu kesinlikle Python 2.7 için yazılmıştır. Cevabımı Python 3.7 için nasıl yapılacağını içerecek şekilde güncelleyeceğim.
copeland3300

Doğrulandı, Python 3.7.6 import sys:; s="Déjà vu Besançon,Lupiñén,Šiauliai,Großräschen,Łódź,Аша,广东省,LA"; for c in s:; w=sys.stdout.write(c+":"+c.encode('utf-8').hex()+"||"); (dışarı)D:44||é:c3a9||j:6a||à:c3a0|| :20||v:76||u:75|| :20||B:42||e:65||s:73||a:61||n:6e||ç:c3a7||o:6f||n:6e||,:2c||L:4c||u:75||p:70||i:69||ñ:c3b1||é:c3a9||n:6e||,:2c||Š:c5a0||i:69||a:61||u:75||l:6c||i:69||a:61||i:69||,:2c||G:47||r:72||o:6f||ß:c39f||r:72||ä:c3a4||s:73||c:63||h:68||e:65||n:6e||,:2c||Ł:c581||ó:c3b3||d:64||ź:c5ba||,:2c||А:d090||ш:d188||а:d0b0||,:2c||广:e5b9bf||东:e4b89c||省:e79c81||,:2c||L:4c||A:41||
bballdave025

20

Fedor Gogolev'in bazı tamamlayıcıları:

İlk olarak, dize 'ASCII kodu' 10'un altında olan karakterler içeriyorsa, gerektiği gibi görüntülenmezler. Bu durumda, doğru biçim şöyle olmalıdır {:02x}:

>>> s = "Hello unicode \u0005 !!"
>>> ":".join("{0:x}".format(ord(c)) for c in s)
'48:65:6c:6c:6f:20:75:6e:69:63:6f:64:65:20:5:20:21:21'
                                           ^

>>> ":".join("{:02x}".format(ord(c)) for c in s)
'48:65:6c:6c:6f:20:75:6e:69:63:6f:64:65:20:05:20:21:21'
                                           ^^

İkincisi, "dizeniz" gerçekte bir "bayt dizesi" ise - ve Python 3'te fark önemli olduğundan - aşağıdakileri tercih edebilirsiniz:

>>> s = b"Hello bytes \x05 !!"
>>> ":".join("{:02x}".format(c) for c in s)
'48:65:6c:6c:6f:20:62:79:74:65:73:20:05:20:21:21'

Bayt nesneleri "0 <= x <256 aralığındaki değişmez bir tamsayı dizisi" olarak tanımlandığından , yukarıdaki kodda dönüştürmeye gerek olmadığını lütfen unutmayın .


11

Bir dize onaltılık bayt olarak yazdırılsın mı?

Kabul edilen cevap:

s = "Hello world !!"
":".join("{:02x}".format(ord(c)) for c in s)

İadeler:

'48:65:6c:6c:6f:20:77:6f:72:6c:64:20:21:21'

Kabul edilen cevap yalnızca bayt kullandığınız sürece (çoğunlukla ascii karakterler) çalışır. Ancak unicode kullanıyorsanız, örneğin:

a_string = u"Привет мир!!" # "Prevyet mir", or "Hello World" in Russian.

Bir şekilde bayta dönüştürmeniz gerekiyor.

Terminaliniz bu karakterleri kabul etmezse UTF-8 kodunu çözebilir veya adları kullanabilirsiniz (böylece kodu benimle birlikte yapıştırabilir ve çalıştırabilirsiniz):

a_string = (
    "\N{CYRILLIC CAPITAL LETTER PE}"
    "\N{CYRILLIC SMALL LETTER ER}"
    "\N{CYRILLIC SMALL LETTER I}"
    "\N{CYRILLIC SMALL LETTER VE}"
    "\N{CYRILLIC SMALL LETTER IE}"
    "\N{CYRILLIC SMALL LETTER TE}"
    "\N{SPACE}"
    "\N{CYRILLIC SMALL LETTER EM}"
    "\N{CYRILLIC SMALL LETTER I}"
    "\N{CYRILLIC SMALL LETTER ER}"
    "\N{EXCLAMATION MARK}"
    "\N{EXCLAMATION MARK}"
)

Görüyoruz ki:

":".join("{:02x}".format(ord(c)) for c in a_string)

İadeler

'41f:440:438:432:435:442:20:43c:438:440:21:21'

kötü / beklenmedik bir sonuç - bunlar, Unicode'da gördüğümüz grafik dünyalarını Unicode Konsorsiyumu'ndan dünyadaki dilleri temsil etmek için birleştiren kod noktalarıdır . Bu değil başka kaynaklar tarafından yorumlanabilir bu yüzden biz aslında yine de, bu bilgileri saklamak nasıl.

Başka bir kaynağın bu verileri kullanmasına izin vermek için genellikle UTF-8 kodlamasına dönüştürmemiz gerekir; örneğin, bu dizeyi baytlara diske kaydetmek veya html'de yayınlamak gerekir. Bu yüzden kod noktalarını UTF-8'in kod birimlerine dönüştürmek için kodlamaya ihtiyacımız var - Python 3'te, tamsayıların tekrarlanabilmesi için ordgerekli değildir bytes:

>>> ":".join("{:02x}".format(c) for c in a_string.encode('utf-8'))
'd0:9f:d1:80:d0:b8:d0:b2:d0:b5:d1:82:20:d0:bc:d0:b8:d1:80:21:21'

Ya da belki de daha şık, yeni f-stringleri kullanarak (sadece Python 3'te mevcuttur):

>>> ":".join(f'{c:02x}' for c in a_string.encode('utf-8'))
'd0:9f:d1:80:d0:b8:d0:b2:d0:b5:d1:82:20:d0:bc:d0:b8:d1:80:21:21'

Python 2'de, önce cgeçin ord, yani ord(c)- daha fazla örnek:

>>> ":".join("{:02x}".format(ord(c)) for c in a_string.encode('utf-8'))
'd0:9f:d1:80:d0:b8:d0:b2:d0:b5:d1:82:20:d0:bc:d0:b8:d1:80:21:21'
>>> ":".join(format(ord(c), '02x') for c in a_string.encode('utf-8'))
'd0:9f:d1:80:d0:b8:d0:b2:d0:b5:d1:82:20:d0:bc:d0:b8:d1:80:21:21'

1
@ not2qubit lütfen bu örnekleri tekrar deneyin - Python 2 ve 3 arasındaki farkları çözmek için biraz zaman ayırdım ve görünüşe göre bunları sadece Python 2 için yazdım. Ve cevabım için teşekkürler!
Aaron Hall

Evet, başardı. Teşekkür ederim!
not2qubit

8

hexdump'S kullanabilirsiniz

import hexdump
hexdump.dump("Hello World", sep=":")

( .lower()küçük harfe ihtiyacınız varsa ekleyin ). Bu hem Python 2 hem de 3 için geçerlidir.


Ayrıca bir sorunla karşılaştım, hexdump veya başka bir paket yüklerken sorun yaşıyorsanız, proxy ayarları nedeniyle pip install -U hexdump --proxy http://proxy.address:port
normalde pip'i

Aslında kullanarak hata yaptım sudoile pipberbat, pacman...
Tobias Kienzler

6

Harita ve lambda işlevini kullanmak, yazdırılabilen (veya başka amaçlarla kullanılan) onaltılı değerlerin bir listesini oluşturabilir

>>> s = 'Hello 1 2 3 \x01\x02\x03 :)'

>>> map(lambda c: hex(ord(c)), s)
['0x48', '0x65', '0x6c', '0x6c', '0x6f', '0x20', '0x31', '0x20', '0x32', '0x20', '0x33', '0x20', '0x1', '0x2', '0x3', '0x20', '0x3a', '0x29']

[hex(ord(c)) for c in s]
Boris

2

Bu, aşağıdaki şekillerde yapılabilir:

from __future__ import print_function
str = "Hello World !!"
for char in str:
    mm = int(char.encode('hex'), 16)
    print(hex(mm), sep=':', end=' ' )

Bunun çıktısı aşağıdaki gibi onaltılı olacaktır:

0x48 0x65 0x6c 0x6c 0x6f 0x20 0x57 0x6f 0x72 0x6c 0x64 0x20 0x21 0x21


geleceği
tofutim

Gelecekte __future__başvurmak üzere, Python 2'nin son sürümlerinde bulunan ve normalde yalnızca Python 3'te özellikleri uyumlu hale getirmek için kullanılabilen standart bir kitaplıktır. Bu yanıtta, Python 2'den sözdiziminin print(text)yerini alan "yazdırma işlevi" özelliğini almak için kullanılır print text. Bkz . Python belgeleri .
Eric Reed

2

Python3 veya iki nokta üst üste ile ilgilenmeyenler için biraz daha genel:

from codecs import encode

data = open('/dev/urandom', 'rb').read(20)
print(encode(data, 'hex'))      # data

print(encode(b"hello", 'hex'))  # string

0

Kullanılması base64.b16encodehalinde python2 (built-in)

>>> s = 'Hello world !!'
>>> h = base64.b16encode(s)
>>> ':'.join([h[i:i+2] for i in xrange(0, len(h), 2)]
'48:65:6C:6C:6F:20:77:6F:72:6C:64:20:21:21'

Bu işe yaramıyor. İçe aktarma için ne kullanıyorsunuz ve neden kullanmıyorsunuz .decode()?
not2qubit

0

Sadece rahatlık için, çok basit.

def hexlify_byteString(byteString, delim="%"):
    ''' very simple way to hexlify a bytestring using delimiters '''
    retval = ""
    for intval in byteString:
        retval += ( '0123456789ABCDEF'[int(intval / 16)])
        retval += ( '0123456789ABCDEF'[int(intval % 16)])
        retval += delim
    return( retval[:-1])

hexlify_byteString(b'Hello World!', ":")
# Out[439]: '48:65:6C:6C:6F:20:57:6F:72:6C:64:21'

0

daha fazla performans sunan bir şey için ''.format()bunu kullanabilirsiniz:

>>> ':'.join( '%02x'%(v if type(v) is int else ord(v)) for v in 'Hello World !!' )
'48:65:6C:6C:6F:20:77:6F:72:6C:64:20:21:21'
>>> 
>>> ':'.join( '%02x'%(v if type(v) is int else ord(v)) for v in b'Hello World !!' )
'48:65:6C:6C:6F:20:77:6F:72:6C:64:20:21:21'
>>> 

üzgünüm bu
sadece güzel yapabilirdi güzel olamazdı '%02x'%v, ama bu sadece int alır ...
ama b''seçmek için mantık olmadan bayt-dizeleri ile sıkışmış olacak ord(v).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.