如何捕获二进制字符串中的所有字符而不被Python解释
这是我重现问题的方法:
首先,创建一个叫做'temp.log'的日志文件,并把这一行粘贴进去:
DEBUG: packetReceived '\x61\x62\x63'
我想要一个脚本,它可以读取日志文件中的这一行,并解码其中的二进制字符串部分('\x61\x62\x63')。为了进行解码,我使用了struct模块,所以:
struct.unpack('BBB', '\x61\x62\x63')
这应该能给我:
(97, 98, 99)
这是我正在使用的脚本:
import re import struct import sys f = open(sys.argv[1], 'r') for line in f: print line packet = re.compile(r"packetReceived \'(.*)\'").search(line).group(1) # packet is the string r'\x61\x62\x63' assert(len(packet), 12) # this works ok (returns (97, 98, 99)) struct.unpack('BBB', '\x61\x62\x63') # this fails because packet is interpreted as r'\\x61\\x62\x63' struct.unpack('BBB', packet)
我运行这个脚本时,把temp.log作为参数传给它。
希望我的注释能突出我的问题。我该如何让变量packet被解释为'\x61\x62\x63'呢?
顺便说一下:在这个问题的第一次编辑中,我以为从文件中读取这一行和这样做是一样的:
line = "DEBUG: packetReceived '\x61\x62\x63'"这会让packet等于'abc'。
但实际上,它和这样做是一样的(使用原始字符串):
line = r"DEBUG: packetReceived '\x61\x62\x63'"4 个回答
2
>>> re.compile(r"packetReceived '(.*)'").search(r"DEBUG: packetReceived '\x61\x62\x63'").group(1)
'\\x61\\x62\\x63'
不,这一行不是你问题的所在。
5
Python 在处理正则表达式时,不会对你传入的字符串进行解释。那些转义序列(比如 \n、\t 等)很可能在你定义变量 line
时就已经被解释过了。举个例子,这样做是没问题的:
line = r"DEBUG: packetReceived '\x61\x62\x63'"
print re.compile(r"packetReceived '(.*)'").search(line).group(1)
它会打印出 \x61\x62\x63
。
1
根据你的问题,数据包 是 等于 '\x61\x62\x63'
。它的长度是12个字节,不是15个也不是3个字节。
让你困惑的是,ipython(我知道你在用这个)和Python解释器在显示值的时候使用了 repr()
这个函数,它会试着把值格式化成你代码里的样子。因为在Python字符串常量中,反斜杠是特殊字符,所以 repr()
会把它们显示成重复的样子,就像在Python代码中那样。
这可能对你有帮助:
for char in packet:
print("%5d %2s %2r" % (ord(char), char, char))
数一数你的字符,看看它们是怎么打印出来的。第一列显示的是字符的序号值,第二列是字符本身,第三列是字符的 repr
表示。
编辑
把最后一行改成:
struct.unpack('BBB', packet)
为:
struct.unpack('BBB', packet.decode('string_escape'))