0

我有一个解析器,它读取一个长八位字节字符串,我希望它根据解析细节打印出更小的字符串。它读取一个十六进制字符串,如下所示

该字符串将采用如下格式:

01046574683001000004677265300000000266010000

十六进制中包含的接口格式如下:

version:length_of_name:name:op_status:priority:reserved_byte

==

01:04:65746830:01:00:00

==(从十六进制转换时)

01:04:eth0:01:00:00 

^ 这是字符串的 1 段,代表 eth0(我插入了 : 以便于阅读)。然而,此刻我的代码返回一个空白列表,我不知道为什么。有人可以帮帮我吗!

def octetChop(long_hexstring, from_ssh_):
    startpoint_of_interface_def=0
    # As of 14/8/13 , the network operator has not been implemented
    network_operator_implemented=False
    version_has_been_read = False
    position_of_interface=0
    chopped_octet_list = []

#This while loop moves through the string of the interface, based on the full length of the container
    try:
        while startpoint_of_interface_def < len(long_hexstring):

            if version_has_been_read == True:
                pass
            else:
                if startpoint_of_interface_def == 0:
                    startpoint_of_interface_def = startpoint_of_interface_def + 2
                    version_has_been_read = True

            endpoint_of_interface_def = startpoint_of_interface_def+2
            length_of_interface_name = long_hexstring[startpoint_of_interface_def:endpoint_of_interface_def]
            length_of_interface_name_in_bytes = int(length_of_interface_name) * 2 #multiply by 2 because its calculating bytes

            end_of_interface_name_point = endpoint_of_interface_def + length_of_interface_name_in_bytes
            hex_name = long_hexstring[endpoint_of_interface_def:end_of_interface_name_point]
            text_name = hex_name.decode("hex")

            print "the text_name is " + text_name

            operational_status_hex = long_hexstring[end_of_interface_name_point:end_of_interface_name_point+2]

            startpoint_of_priority = end_of_interface_name_point+2
            priority_hex = long_hexstring[startpoint_of_priority:startpoint_of_priority+2]

            #Skip the reserved byte
            network_operator_length_startpoint = startpoint_of_priority+4

            single_interface_string = long_hexstring[startpoint_of_interface_def:startpoint_of_priority+4]
            print single_interface_string + " is chopped from the octet string"# - keep for possible debugging

            startpoint_of_interface_def = startpoint_of_priority+4

            if network_operator_implemented == True:
                network_operator_length = long_hexstring[network_operator_length_startpoint:network_operator_length_startpoint+2]
                network_operator_length = int(network_operator_length) * 2
                network_operator_start_point = network_operator_length_startpoint+2
                network_operator_end_point = network_operator_start_point + network_operator_length
                network_operator = long_hexstring[network_operator_start_point:network_operator_end_point]
                #
                single_interface_string = long_hexstring[startpoint_of_interface_def:network_operator_end_point]

                #set the next startpoint if there is one
                startpoint_of_interface_def = network_operator_end_point+1
            else:
                self.network_operator = None

            print single_interface_string + " is chopped from the octet string"# - keep for possible debugging

            #This is where each individual interface is stored, in a list for comparison.
            chopped_octet_list.append(single_interface_string)
    finally:

        return chopped_octet_list
4

5 回答 5

1

我希望我说对了。你得到一个包含各种接口定义的十六进制字符串。在每个接口定义中,第二个八位字节描述了接口名称的长度。

假设字符串包含接口 eth0 和 eth01,看起来像这样(eth0 的长度为 4,eth01 的长度为 5):

01046574683001000001056574683031010000

然后你可以像这样拆分它:

def splitIt (s):
    tokens = []
    while s:
        length = int (s [2:4], 16) * 2 + 10 #name length * 2 + 10 digits for rest
        tokens.append (s [:length] )
        s = s [length:]
    return tokens

这产生:

['010465746830010000', '01056574683031010000']
于 2013-08-15T15:34:39.983 回答
1

您的代码返回空白列表的原因如下: 在这一行中:

    else:
        self.network_operator = None

self没有定义,所以你得到一个NameError异常。这意味着try直接跳转到finally子句,而无需执行您执行以下操作的部分:

chopped_octet_list.append(single_interface_string)

结果,列表仍然是空的。无论如何,此类任务的代码过于复杂,我会遵循其他答案之一。

于 2013-08-15T15:51:56.587 回答
0

要添加到 Hyperboreus 的答案,这是一种在拆分接口字符串后解析它们的简单方法:

def parse(s):
    version = int(s[:2], 16)
    name_len = int(s[2:4], 16)
    name_end = 4 + name_len * 2
    name = s[4:name_end].decode('hex')
    op_status = int(s[name_end:name_end+2], 16)
    priority = int(s[name_end+2:name_end+4], 16)
    reserved = s[name_end+4:name_end+6]
    return version, name_len, name, op_status, priority, reserved

这是输出:

>>> parse('010465746830010000')
(1, 4, 'eth0', 1, 0, '00')
于 2013-08-15T15:42:41.237 回答
0

检查以下是否有帮助。调用parse下面的方法并将字符串流传递给它,然后迭代以获取卡信息(希望我没听错:))parse将返回您所需信息的元组。

>>> def getbytes(hs):
    """Returns a generator of bytes from a hex string"""
    return (int(hs[i:i+2],16) for i in range(0,len(hs)-1,2))

>>> def get_single_card_info(g):
    """Fetches a single card info from a byte generator"""
    v = g.next()
    l = g.next()
    name = "".join(chr(x) for x in map(lambda y: y.next(),[g]*l))
    return (str(v),name,g.next(),g.next(),g.next())

>>> def parse(hs):
    """Parses a hex string stream and returns a generator of card infos"""
    bs = getbytes(hs)
    while True:
        yield get_single_card_info(bs)


>>> c = 1
>>> for card in parse("01046574683001000001056574683031010000"):
    print "Card:{0} -> Version:{1}, Id:{2}, Op_stat:{3}, priority:{4}, reserved:{5} bytes".format(c,*card)
    c = c + 1


Card:1 -> Version:1, Id:eth0, Op_stat:1, priority:0, reserved:0 bytes
Card:2 -> Version:1, Id:eth01, Op_stat:1, priority:0, reserved:0 bytes
于 2013-08-15T16:12:46.870 回答
0

Pyparsing 包含一个用于解析计数的元素数组的内置表达式,因此这将很好地处理您的“名称”字段。这是整个解析器:

from pyparsing import Word,hexnums,countedArray

# read in 2 hex digits, convert to integer at parse time
octet = Word(hexnums,exact=2).setParseAction(lambda t:int(t[0],16))

# read in a counted array of octets, convert to string
nameExpr = countedArray(octet, intExpr=octet)
nameExpr.setParseAction(lambda t: ''.join(map(chr,t[0])))

# define record expression, with named results
recordExpr = (octet('version') + nameExpr('name') + octet('op_status') +
              octet('priority') #+ octet('reserved'))

解析您的样本:

sample = "01046574683001000004677265300000000266010000"
for rec in recordExpr.searchString(sample):
    print rec.dump()

给出:

[1, 'eth0', 1, 0]
- name: eth0
- op_status: 1
- priority: 0
- version: 1
[0, 'gre0', 0, 0]
- name: gre0
- op_status: 0
- priority: 0
- version: 0
[0, 'f\x01', 0, 0]
- name: f
- op_status: 0
- priority: 0
- version: 0

dump() 方法显示可用于访问单独解析的位的结果名称,例如rec.namerec.version

(我注释掉了保留字节,否则第二个条目将无法正确解析。此外,第三个条目包含一个带有 \x01 字节的名称。)

于 2013-08-15T16:43:58.410 回答