如何在Python中解析具有八进制值的char数组?

时间:2013-11-09 01:11:06

标签: python-2.7 arrays octal

编辑:我应该注意,我想要任何十六进制数组的一般情况,而不仅仅是我提供的谷歌数据。

编辑背景:背景是网络:我正在解析DNS数据包并尝试获取其QNAME。我将整个数据包作为字符串接收,每个字符代表一个字节。显然这个问题看起来像一个Pascal字符串问题,并且使用struct模块似乎是要走的路。

我在Python 2.7中有一个包含八进制值的char数组。例如,假设我有一个数组

DNS = "\03www\06google\03com\0"

我想得到:

  

www.google.com

这是一种有效的方法吗?我的第一个想法是迭代DNS char数组并将chars添加到我的新数组答案。每当我看到'\'字符时,我会忽略它后面的'\'和两个字符。有没有办法在不使用新阵列的情况下获得结果www.google.com?

我恶心的实现(我的回答是一系列字符,这不是我想要的,我只想要字符串www.google.com:

DNS = "\\03www\\06google\\03com\\0"
answer = []
i = 0
while i < len(DNS):
    if DNS[i] == '\\' and DNS[i+1] != 0:
        i += 3    
    elif DNS[i] == '\\' and DNS[i+1] == 0:
        break
    else:
        answer.append(DNS[i])
        i += 1

4 个答案:

答案 0 :(得分:2)

既然你已经解释了你的真实问题,那么到目前为止你得到的答案都不会有效。为什么?因为它们可以从字符串中删除\03之类的序列。但是你没有像<{1}}这样的 序列,你有单个控制字符。

当然,你可以做类似的事情,只需用点替换任何控制字符。

但是你真正尝试做的事情并不是用点替换控制字符,而是解析DNS数据包。

DNS由RFC 1035定义。 DNS数据包中的QNAME是:

  

表示为标签序列的域名,其中每个标签由长度八位字节后跟该八位字节数组成。域名以根的空标签的零长度八位字节终止。注意,该字段可以是奇数个八位字节;没有使用填充。

所以,让我们解析一下。如果你理解“由长度八位字节组成的标签后跟那个八位字节的数字”与“Pascal字符串”有什么关系,那就更快了。另外,你可以写得更干净,更简洁地作为一个发生器。但是,让我们这样做死的简单方法:

\03

答案 1 :(得分:1)

import re
DNS = "\\03www\\06google\\03com\\0"
m = re.sub("\\\\([0-9,a-f]){2}", "", DNS)
print(m)

答案 2 :(得分:1)

也许是这样的?

#!/usr/bin/python3

import re

def convert(adorned_hostname):
    result1 = re.sub(r'^\\03', '', adorned_hostname )
    result2 = re.sub(r'\\0[36]', '.', result1)
    result3 = re.sub(r'\\0$', '', result2)
    return result3

def main():
    adorned_hostname = r"\03www\06google\03com\0"
    expected_result = 'www.google.com'
    actual_result = convert(adorned_hostname)
    print(actual_result, expected_result)
    assert actual_result == expected_result

main()

答案 3 :(得分:1)

对于最初提出的问题,用点代替"\\03www\\06google\\03com\\0"等字符串中的反斜杠 - 十六进制序列......

如果您想使用正则表达式执行此操作:

  • \\匹配反斜杠。
  • [0-9A-Fa-f]匹配任何十六进制数字。
  • [0-9A-Fa-f]+匹配一个或多个十六进制数字。
  • \\[0-9A-Fa-f]+匹配反斜杠后跟一个或多个十六进制数字。

你想找到每个这样的序列,并用点替换它,对吗?如果查看re文档,您将找到一个名为sub的函数,该函数用于替换带有替换字符串的模式:

re.sub(r'\\[0-9A-Fa-f]+', '.', DNS)

我怀疑这些可能实际上是八进制,而不是十六进制,在这种情况下你需要[0-7]而不是[0-9A-Fa-f],但没有其他任何东西会改变。


另一种方法是识别这些是有效的Python转义序列。并且,如果我们将它们转移到它们来自的位置(例如,使用DNS.decode('string_escape')),则会变成一系列长度前缀(也称为“Pascal”)字符串,这是一种可以在任何数字中解析的标准格式方法,包括stdlib struct模块。这样做的好处是可以在读取数据时验证数据,并且不会被任何可能出现的误报所抛弃,例如,如果其中一个字符串组件在其中间有反斜杠。

当然,这更多地假定数据。似乎很可能这个的真正含义是“一系列长度为前缀的字符串,连接,然后反斜杠转义”,在这种情况下你应该解析它。但它可能只是看起来像是巧合,在这种情况下,解析它是一个非常糟糕的主意。