2

I read a printed byte in a file, as a string:

a = "b'\xa0-\xfc\xa3\xf8\xd9'" 

type(a) is str.

How should I decode it?

The decoded value should be a02dfca3f8d9.

A part the file is uploaded here: https://www.dropbox.com/s/p12pwwhknu3gr4h/info.log?dl=1

[PICA8-P3297] dl-dst output #1 OFPFlowMod(actions=[OFPActionOutput(max_len=65509,port=45)],buffer_id=4294967295,command=0,cookie=16895774056056650001,flags=0,hard_timeout=0,idle_timeout=0,match=OFPMatch(dl_dst=b'\xa0-\xfc\xa3\xf8\xd9',dl_src=b'\x00\x00\x00\x00\x00\x00',dl_type=0,dl_vlan=0,dl_vlan_pcp=0,in_port=0,nw_dst=0,nw_proto=0,nw_src=0,nw_tos=0,tp_dst=0,tp_src=0,wildcards=4194295),out_port=65535,priority=1)

I open and get the dl_dst value in the file by this line:

dl_dst = fm_line.split('OFPMatch')[1].split(',')[0].split('=')[1]

dl_dst is supposed to be a Mac Address. My question is how to convert it?

As suggested, I tried:

print(''.join(["{0:x}".format(ord(char)) for char in dl_dst[2:-1]]))

But the printed resuls is 275c5c7861302d5c5c7866635c5c7861335c5c7866385c5c78643927, which is not what I expected.

mcqueenvh
  • 31
  • 2
  • 1
    That does not appear to be a valid byte string, where did you get it? – Error - Syntactical Remorse Jun 07 '19 at 17:23
  • 1
    How did this string: `a = "b'\xa0-\xfc\xa3\xf8\xd9'" ` come about? It *looks* like someone had a bytes object, then wrote the *string representation of a bytes object* to a file. You should fix that. You *cannot decode a string*, you can *encode* a string to bytes, and *decode bytes* to strings. You could use `eval` here to get the bytes represented by that string – juanpa.arrivillaga Jun 07 '19 at 17:40
  • Please add the line that breaks my solution as well. – Error - Syntactical Remorse Jun 07 '19 at 18:47
  • Done. Your solution does not break, but does not give the correct answer (ONLY when I read the value from the file). – mcqueenvh Jun 07 '19 at 18:52

1 Answers1

3

This should get you the result you want assuming a is a escaped str.

a = "b'\xa0-\xfc\xa3\xf8\xd9'"
res = ["{0:x}".format(ord(char)) for char in a[2:-1]]
res = ''.join(res)
print(res) # a02dfca3f8d9

Note:
a[2:-1] removes the b' and ' from the input str.
ord() returns the integer of a unicode character.
{0:x} returns a str hex representation of a given int.
''.join turns the entire list into one str.

That can be onelined but for convenience and readability I left it as two.

Note you should probably fix your source so it does not output that way (it should not output b'...' to a file).


- EDIT -

Since you have a raw str it needs to be done differently. Instead of doing split to get the MAC address from your fm_line just use regex (less hassle), also your file is reading in raw strings meaning \ becomes escaped so you need to fix that. This solution will work for raw or escaped strings.

import re
import ast
get_mac = re.compile(r"dl_dst=b'(.+?)',") # This should be outside of your loop.
result = get_mac.search(fm_line) # This you will call for each line that you need to parse
if result:
    address = ast.literal_eval(f"'{result.group(1)}'") # This will turn your raw `str` in an escaped `str`
    res = ["{0:x}".format(ord(char)) for char in address]
    res = ''.join(res)
    print(res)