0

長いオクテット文字列を読み取るパーサーがあり、解析の詳細に基づいて小さな文字列を出力したいと考えています。次のような16進文字列で読み取ります

文字列は次のような形式になります。

01046574683001000004677265300000000266010000

16 進数に含まれるインターフェイスの形式は次のようになります。

version:length_of_name:name:op_status:priority:reserved_byte

==

01:04:65746830:01:00:00

== (16進数から換算した場合)

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

コードが空のリストを返す理由は次のとおりです。

    else:
        self.network_operator = None

selfは定義されていないため、NameError例外が発生します。これは、次の部分を実行することなくtry、節に直接ジャンプすることを意味します。finally

chopped_octet_list.append(single_interface_string)

結果として、リストは空のままです。いずれにせよ、そのようなタスクのコードは非常に複雑です。他の回答のいずれかに従います。

于 2013-08-15T15:51:56.587 に答える
1

私はあなたが正しいことを願っています。さまざまなインターフェイス定義を含む 16 進文字列を取得しました。各インターフェイス定義内の 2 番目のオクテットは、インターフェイスの名前の長さを示します。

文字列にインターフェイス 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 に答える
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

rec.namedump() メソッドは、やなど、個別に解析されたビットにアクセスするために使用できる結果名を表示しますrec.version

(予約済みバイトをコメントアウトしました。そうしないと、2 番目のエントリが正しく解析されません。また、3 番目のエントリには \x01 バイトの名前が含まれています。)

于 2013-08-15T16:43:58.410 に答える
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 に答える