我最近开始使用python / pyparsing处理一串十六进制值,我遇到了这个问题: 考虑一下这个字符串:
string = "10020304059917368584304025326"
我希望最终结果如下:
['10', '02', '03', ['04', '05', '9917365843'], ['04', '02', '5326']]
假设04是表示数据的标签(与ASN.1中的概念相同),05是该数据的大小。我没有看到如何在pyparsing代码上使用size变量。我能做的最好的事情是:
byte = Word(hexnums, exact=2)
process = byte + byte + byte + Word(hexnums)
newstring = process.parseString(string)
print (newstring.dump())
非常感谢任何帮助。
PS :在Hooked的帮助下,我的最终代码为:
from pyparsing import *
string = "10 02 03 04 05 99 17 36 58 43 04 02 53 26"
tag = Word(hexnums, exact=2)
size = Word(hexnums)
array = Group(tag + countedArray(size))
process = tag + tag + tag + ZeroOrMore(array)
newstring = process.parseString(string)
print (newstring.dump())
打印哪些:
['10', '02', '03', ['04', ['99', '17', '36', '58', '43']], ['04', ['53', '26']]]
希望这有助于将来。
答案 0 :(得分:2)
我在更广泛的意义上问了同样的问题Can a BNF handle forward consumption?。这个问题的答案是否定的,因为无上下文语法无法知道将要发生什么。值得庆幸的是,pyparsing不仅仅是一个无上下文的语法,而是作为包points out的作者:
Pyparsing包含帮助器
countedArray
,它完全符合您的要求。它需要一个参数expr,并将解析一个整数,后跟'n'个expr实例
在他的回答中提供了一个更完整的解决方案,其中包含一个最小的工作示例。问题:PyParsing lookaheads and greedy expressions也是您尝试做的很好的参考。
答案 1 :(得分:0)
这会有用吗?它不使用pyparsing,但它会在看到'04'时记录可变长度的子列表。
def func( s ):
d = []
# while s isn't empty
while len(s) != 0:
b = s[0:2]
if b != '04':
# if b isn't '04' append it to d
d.append( b )
# shorten s
s = s[2:]
else:
# take the length, as a string
l = s[2:4]
# take the length, as an integer
n = int(s[2:4])
# record b='04', the length, and then the next values
d.append( [ b, l, s[4:4+n*2] ] )
# shorten s
s = s[4+n*2:]
return d