У меня есть эта строка: Hello world !!
и я хочу напечатать ее, используя Python как48:65:6c:6c:6f:20:77:6f:72:6c:64:20:21:21
.
hex()
работает только для целых чисел.
Как это можно сделать?
У меня есть эта строка: Hello world !!
и я хочу напечатать ее, используя Python как48:65:6c:6c:6f:20:77:6f:72:6c:64:20:21:21
.
hex()
работает только для целых чисел.
Как это можно сделать?
Ответы:
Вы можете преобразовать вашу строку в генератор int, применить шестнадцатеричное форматирование для каждого элемента и вставить его в разделитель:
>>> 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
str
виде гекса не имеет смысла; Вы хотите напечатать bytes
объект как шестнадцатеричный (преобразовать str
в bytes
вызов .encode()
).
":".join("{:02x}".format(ord(c)) for c in 'løl')
возвращается '6c:f8:6c'
, в то время как ":".join("{:02x}".format(c) for c in 'løl'.encode())
дает правильное представление UTF-8 '6c:c3:b8:6c'
.
":".join("{:04x}".format(ord(c)) for c in s)
(заменяющий 02x
с 04x
к нулевой площадке каждому номера из 4 цифр) вместо
WARNING: Calling str(pkt) on Python 3 makes no sense!
':'.join(x.encode('hex') for x in 'Hello World!')
h = binascii.hexlify(b"Hello world !!") to get hex string. b":".join(h[i:i+2] for i in range(0, len(h), 2))
вставлять ':'
после каждых двух шестнадцатеричных цифр в нем.
LookupError: 'hex' is not a text encoding; use codecs.encode() to handle arbitrary codecs
Для Python 2.x:
':'.join(x.encode('hex') for x in 'Hello World!')
Код выше не будет работать с Python 3.x , для 3.x код ниже будет работать:
':'.join(hex(ord(x))[2:] for x in 'Hello World!')
Другой ответ в две строки, который некоторым может показаться более легким для чтения, помогает при отладке разрывов строк или других нечетных символов в строке:
Для Python 2.7
for character in string:
print character, character.encode('hex')
Для Python 3.7 (не тестируется на всех выпусках 3)
for character in string:
print(character, character.encode('utf-8').hex())
codecs.encode(<bytestring>, "hex")
работает, хотя.
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: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||
Некоторые дополнения к ответу Федора Гоголева:
Во-первых, если строка содержит символы, чей «код ASCII» меньше 10, они не будут отображаться, как требуется. В этом случае правильный формат должен быть {: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'
^^
Во-вторых, если ваша «строка» на самом деле является «байтовой строкой» - и поскольку различие имеет значение в Python 3 - вы можете предпочесть следующее:
>>> 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'
Обратите внимание, что в приведенном выше коде нет необходимости в преобразовании, поскольку объекты байтов определены как «неизменяемая последовательность целых чисел в диапазоне 0 <= x <256» .
Вывести строку в виде шестнадцатеричных байтов?
Принятый ответ дает:
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'
Принятый ответ работает только до тех пор, пока вы используете байты (в основном символы ascii). Но если вы используете Unicode, например:
a_string = u"Привет мир!!" # "Prevyet mir", or "Hello World" in Russian.
Вам нужно как-то преобразовать в байты.
Если ваш терминал не принимает эти символы, вы можете декодировать из UTF-8 или использовать имена (чтобы вы могли вставить и запустить код вместе со мной):
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}"
)
Итак, мы видим, что:
":".join("{:02x}".format(ord(c)) for c in a_string)
возвращается
'41f:440:438:432:435:442:20:43c:438:440:21:21'
плохой / неожиданный результат - это те кодовые точки, которые объединяются для создания графем, которые мы видим в Unicode, от Консорциума Unicode - представляющих языки во всем мире. Это не то, как мы на самом деле храним эту информацию, поэтому она может быть интерпретирована другими источниками.
Чтобы позволить другому источнику использовать эти данные, нам обычно необходимо преобразовать кодировку в UTF-8, например, чтобы сохранить эту строку в байтах на диск или опубликовать в html. Поэтому нам нужно, чтобы кодирование для преобразования кодовых точек в кодовые единицы UTF-8 - в Python 3 ord
не требуется, поскольку 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'
Или, возможно, более элегантно, используя новые f-строки (доступно только в Python 3):
>>> ":".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 перейдите c
к ord
первому, т. Е. ord(c)
- больше примеров:
>>> ":".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'
Вы можете использовать hexdump
«S
import hexdump
hexdump.dump("Hello World", sep=":")
(добавьте, .lower()
если вам требуется строчные буквы). Это работает как для Python 2 и 3.
pip install -U hexdump --proxy http://proxy.address:port
sudo
с pip
, что испортило pacman
...
С помощью функции map и lambda можно получить список шестнадцатеричных значений, которые можно распечатать (или использовать для других целей).
>>> 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]
Это можно сделать следующими способами:
from __future__ import print_function
str = "Hello World !!"
for char in str:
mm = int(char.encode('hex'), 16)
print(hex(mm), sep=':', end=' ' )
Вывод этого будет в шестнадцатеричном виде следующим образом:
0x48 0x65 0x6c 0x6c 0x6f 0x20 0x57 0x6f 0x72 0x6c 0x64 0x20 0x21 0x21
__future__
- это стандартная библиотека, доступная в последних версиях Python 2, которую можно использовать для создания функций, обычно только в Python 3 с обратной совместимостью. В этом ответе он используется для получения print(text)
функции «функция печати», которая заменяет print text
синтаксис из Python 2. См. Документы по Python .
Немного более общий для тех, кто не заботится о Python3 или двоеточиях:
from codecs import encode
data = open('/dev/urandom', 'rb').read(20)
print(encode(data, 'hex')) # data
print(encode(b"hello", 'hex')) # string
Использование base64.b16encode
в python2 (его встроенный)
>>> 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'
.decode()
?
Просто для удобства, очень просто.
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'
для чего-то, что предлагает большую производительность, чем ''.format()
, вы можете использовать это:
>>> ':'.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'
>>>
извините, это не выглядело
бы лучше, было бы неплохо, если бы можно было просто сделать '%02x'%v
, но это занимает только int ...
но вы застряли с байтовыми строками b''
без логики для выбора ord(v)
.
str
или Python 3bytestring
), поскольку нет однозначного преобразования символа в целое число в 0 ... 255. Таким образом, строки символов (Python 2unicode
и Python 3str
) сначала требуют некоторой кодировки, прежде чем они будут преобразованы в этот шестнадцатеричный формат. Ответ Аарона Холла иллюстрирует это.