Python Hexadecimal - python

How to convert decimal to hex in the following format (at least two digits, zero-padded, without an 0x prefix)?
Input: 255 Output:ff
Input: 2 Output: 02
I tried hex(int)[2:] but it seems that it displays the first example but not the second one.

Use the format() function with a '02x' format.
>>> format(255, '02x')
'ff'
>>> format(2, '02x')
'02'
The 02 part tells format() to use at least 2 digits and to use zeros to pad it to length, x means lower-case hexadecimal.
The Format Specification Mini Language also gives you X for uppercase hex output, and you can prefix the field width with # to include a 0x or 0X prefix (depending on wether you used x or X as the formatter). Just take into account that you need to adjust the field width to allow for those extra 2 characters:
>>> format(255, '02X')
'FF'
>>> format(255, '#04x')
'0xff'
>>> format(255, '#04X')
'0XFF'

I think this is what you want:
>>> def twoDigitHex( number ):
... return '%02x' % number
...
>>> twoDigitHex( 2 )
'02'
>>> twoDigitHex( 255 )
'ff'

Another solution is:
>>> "".join(list(hex(255))[2:])
'ff'
Probably an archaic answer, but functional.

Related

How to make the correct regular expression with hexadecimal value?

I am focusing on data with a regular expression. I am using python and I implement this function:
import re
exp = r"\bTimestamp\s+([0-9]+)\s+ID=(\w{32})0*\s+Dest_ID=(\w{32})0*\sASN_Received\s+(?!0000)[0-9A-F]{4}+"
rx = re.compile(exp)
m=rx.match("Timestamp 1549035123 ID=02141592cc0000000300000000000000 Dest_ID=00000000000000000000000000000000 Nbr_Received = ec30000000")
m.groups()
print(m.groups())
But it does not work correctly:
I expect to have this result:
('1549033267', '02141592cc0000000500000000000000','00000000000000000000000000000000','ec30000000')
Then I want to convert the hexadecimal value to decimal by using this function:
def Convert_Decimal(nbr_hex):
nbr_dec = nbr_hex[5] + nbr_hex[2:4] + nbr_hex[0:2]
reversed = int(nbr_dec, 16)
print(reversed)
As finalresult I want to have:
('1549033267', '02141592cc0000000500000000000000','00000000000000000000000000000000','12524')
Hexadecimal values use the digits 0-9 and the letters A through to F (upper or lowercase), only, and in your case are of a fixed length, so [0-9a-fA-F]{32} suffices to match those values. You don't need to match trailing zeros, when you have a fixed-length value.
You really don't want to use \w here, you wouldn't want to match underscores, the rest of the English alphabet, or any other letter-like symbol in the Unicode standard (there are thousands).
Next, you are looking for ASN_Received, but your input string uses the text Nbr_Received = with whitespace around the = character. Account for that:
exp = (
r'\bTimestamp\s+([0-9]+)\s+'
r'ID=([0-9a-fA-F]{32})\s+'
r'Dest_ID=([0-9a-fA-F]{32})\s+'
r'Nbr_Received\s*=\s*([0-9a-fA-F]{4,})'
)
I broke the expression across multiple lines to be easier to follow. Note that I used {4,} for the last hexadecimal value, matching 4 or more digits. You can't use + and {n,m} patterns together, choose one or the other.
You then get:
>>> import re
>>> exp = (
... r'\bTimestamp\s+([0-9]+)\s+'
... r'ID=([0-9a-fA-F]{32})\s+'
... r'Dest_ID=([0-9a-fA-F]{32})\s+'
... r'Nbr_Received\s*=\s*([0-9a-fA-F]{4,})'
... )
>>> rx = re.compile(exp)
>>> m = rx.match("Timestamp 1549035123 ID=02141592cc0000000300000000000000 Dest_ID=00000000000000000000000000000000 Nbr_Received = ec30000000")
>>> print(m.groups())
('1549035123', '02141592cc0000000300000000000000', '00000000000000000000000000000000', 'ec30000000')
Also see this online demo at regex101, which explains each part of the pattern on the right-hand side.
I'd convert the last hexadecimal number via bytes.fromhex() and int.from_bytes() to an integer:
>>> m.group(4)
'ec30000000'
>>> bytes.fromhex(m.group(4))
b'\xec0\x00\x00\x00'
>>> int.from_bytes(bytes.fromhex(m.group(4)), 'little')
12524
Try this:
>>> import re
>>> string = "Timestamp 1549035123 ID=02141592cc0000000300000000000000 Dest_ID=00000000000000000000000000000000 Nbr_Received = ec30000000"
>>> pat = r'Timestamp\s+(\d+)\s+ID=(\w+)\s+Dest_ID=(\d+)\s+Nbr_Received\s+?=\s+?(\w+)'
>>> re.findall(pat, string)
[('1549035123', '02141592cc0000000300000000000000', '00000000000000000000000000000000', 'ec30000000')]

Python integer to hex string with padding

Consider an integer 2. I want to convert it into hex string '0x02'. By using python's built-in function hex(), I can get '0x2' which is not suitable for my code. Can anyone show me how to get what I want in a convenient way? Thank you.
integer = 2
hex_string = '0x{:02x}'.format(integer)
See pep 3101, especially Standard Format Specifiers for more info.
For integers that might be very large:
integer = 2
hex = integer.to_bytes(((integer.bit_length() + 7) // 8),"big").hex()
The "big" refers to "big endian"... resulting in a string that is aligned visually as a human would expect.
You can then stick "0x" on the front if you want.
hex = "0x" + hex
>>> integer = 2
>>> hex_string = format(integer, '#04x') # add 2 to field width for 0x
>>> hex_string
'0x02'
See Format Specification Mini-Language

as I hold the string of hexadecimal format without encoding the string?

The general problem is that I need the hexadecimal string stays in that format to assign it to a variable and not to save the coding?
no good:
>>> '\x61\x74'
'at'
>>> a = '\x61\x74'
>>> a
'at'
works well, but is not as:
>>> '\x61\x74'
'\x61\x74' ????????
>>> a = '\x61\x74'
>>> a
'\x61\x74' ????????
Use r prefix (explained on SO)
a = r'\x61\x74'
b = '\x61\x74'
print (a) #prints \x61\x74
print (b) # prints at
It is the same data. Python lets you specify a literal string using different methods, one of which is to use escape codes to represent bytes.
As such, '\x61' is the same character value as 'a'. Python just chooses to show printable ASCII characters as printable ASCII characters instead of the escape code, just because that makes working with bytestrings that much easier.
If you need the literal slash, x character and the two digit 6 and 1 characters (so a string of length 4), you need to double the slash or use raw strings.
To illustrate:
>>> '\x61' == 'a' # two notations for the same value
True
>>> len('\x61') # it's just 1 character
1
>>> '\\x61' # escape the escape
'\\x61'
>>> r'\x61' # or use a raw literal instead
'\\x61'
>>> len('\\x61') # which produces 4 characters
4

How to convert an integer to hexadecimal without the extra '0x' leading and 'L' trailing characters in Python?

I am trying to convert big integer number to hexadecimal, but in result I get extra "0x" in the beginning and "L" at the and. Is there any way to remove them. Thanks.
The number is:
44199528911754184119951207843369973680110397865530452125410391627149413347233422
34022212251821456884124472887618492329254364432818044014624401131830518339656484
40715571509533543461663355144401169142245599341189968078513301836094272490476436
03241723155291875985122856369808620004482511813588136695132933174030714932470268
09981252011612514384959816764532268676171324293234703159707742021429539550603471
00313840833815860718888322205486842202237569406420900108504810
In hex I get:
0x2ef1c78d2b66b31edec83f695809d2f86e5d135fb08f91b865675684e27e16c2faba5fcea548f3
b1f3a4139942584d90f8b2a64f48e698c1321eee4b431d81ae049e11a5aa85ff85adc2c891db9126
1f7f2c1a4d12403688002266798ddd053c2e2670ef2e3a506e41acd8cd346a79c091183febdda3ca
a852ce9ee2e126ca8ac66d3b196567ebd58d615955ed7c17fec5cca53ce1b1d84a323dc03e4fea63
461089e91b29e3834a60020437db8a76ea85ec75b4c07b3829597cfed185a70eeaL
The 0x is literal representation of hex numbers. And L at the end means it is a Long integer.
If you just want a hex representation of the number as a string without 0x and L, you can use string formatting with %x.
>>> a = 44199528911754184119951207843369973680110397
>>> hex(a)
'0x1fb62bdc9e54b041e61857943271b44aafb3dL'
>>> b = '%x' % a
>>> b
'1fb62bdc9e54b041e61857943271b44aafb3d'
Sure, go ahead and remove them.
hex(bignum).rstrip("L").lstrip("0x") or "0"
(Went the strip() route so it'll still work if those extra characters happen to not be there.)
Similar to Praveen's answer, you can also directly use built-in format().
>>> a = 44199528911754184119951207843369973680110397
>>> format(a, 'x')
'1fb62bdc9e54b041e61857943271b44aafb3d'
I think it's dangerous idea to use strip.
because lstrip or rstrip strips 0.
ex)
a = '0x0'
a.lstrip('0x')
''
result is '', not '0'.
In your case, you can simply use replace to prevent above situation.
Here's sample code.
hex(bignum).replace("L","").replace("0x","")
Be careful when using the accepted answer as lstrip('0x') will also remove any leading zeros, which may not be what you want, see below:
>>> account = '0x000067'
>>> account.lstrip('0x')
'67'
>>>
If you are sure that the '0x' prefix will always be there, it can be removed simply as follows:
>>> hex(42)
'0x2a'
>>> hex(42)[2:]
'2a'
>>>
[2:] will get every character in the string except for the first two.
A more elegant way would be
hex(_number)[2:-1]
but you have to be careful if you're working with gmpy mpz types,
then the 'L' doesn't exist at the end and you can just use
hex(mpz(_number))[2:]

Convert string into integer

How can I convert string into integer and remove every character from that change.
Example:
S = "--r10-" I want to have this: S = 10
This not work:
S = "--10-"
int(S)
You can use filter(str.isdigit, s) to keep only those characters of s that are digits:
>>> s = "--10-"
>>> int(filter(str.isdigit, s))
10
Note that this might lead to unexpected results for strings that contain multiple numbers
>>> int(filter(str.isdigit, "12 abc 34"))
1234
or negative numbers
>>> int(filter(str.isdigit, "-10"))
10
Edit: To make this work for unicode objects instead of str objects, use
int(filter(unicode.isdigit, u"--10-"))
remove all non digits first like that:
int(''.join(c for c in "abc123def456" if c.isdigit()))
You could just strip off - and r:
int("--r10-".strip('-r'))
use regex replace with /w to replace non word characters with "" empty string. then cast it
I prefer Sven Marnach's answer using filter and isdigit, but if you want you can use regular expressions:
>>> import re
>>> pat = re.compile(r'\d+') # '\d' means digit, '+' means one or more
>>> int(pat.search('--r10-').group(0))
10
If there are multiple integers in the string, it pulls the first one:
>>> int(pat.search('12 abc 34').group(0))
12
If you need to deal with negative numbers use this regex:
>>> pat = re.compile(r'\-{0,1}\d+') # '\-{0,1}' means zero or one dashes
>>> int(pat.search('negative: -8').group(0))
-8
This is simple and does not require you to import any packages.
def _atoi(self, string):
i = 0
for c in string:
i += ord(c)
return i

Categories

Resources