2014-02-18 61 views
0

如何解析python中的二进制数字序列。 以下是我想要做的一个例子。解析一串二进制数字

我有二进制数字的序列,例如

sequence = '1110110100110111011011110101100101100' 

和,我需要解析这个和提取数据。

说上述序列含有开始,ID,数据和结束字段

启动是一个2比特字段,ID是8位字段,数据字段可以从1至8192位变化,并且端为4位字段。

和解析后,我期待输出如下:

result = {start : 11, 
      id : 10110100, 
      data : 11011101101111010110010, 
      end : 1100, 
     } 

我使用这个在我的应用程序之一。 我能够使用正则表达式解析序列,但问题是正则表达式必须由用户编写。所以作为替代方案,我使用BNF语法作为语法更具可读性。

我试着解决这个使用python的简约 pyparsing解析器。但我无法找到可变长度字段的解决方案。

i的简约可写为Python语法如下:

grammar = """sequence = start id data end 

start = ~"[01]{2}" 
id = ~"[01]{8}" 
data = ~"[01]{1,8192}" 
end = ~"[01]{4}" 
""" 

由于数据字段的长度是可变的,并且分析器是贪心,上述序列是不能够匹配与上述语法。解析器将结束字段位带入数据字段。

我只是简化了我的问题,以上面的例子。

让我描述的全部问题。有3种数据包(让我们称它们为令牌,握手和数据包)。令牌和握手包的长度是固定的,数据包长度可变。 (以上示出的示例是用于数据分组的例子)

输入包括比特的连续流的。每个数据包的开始都由“开始”模式标记,数据包结束由“结束”模式标记。这两种都是固定位模式。

例令牌分组语法:

start - 2 bits, id - 8 bits, address - 7bits, end - 4bits 
111011010011011101100 

例握手分组语法:

start - 2 bits, id - 8bits, end - 4 bits 
11101101001100 

例顶层规则:

packet = tokenpacket | datapacket | handshakepacket 

如果只有一个类型的数据包,然后切片会工作。但是当我们开始分析时,我们不知道哪个数据包最终会匹配。这就是为什么我考虑使用语法,因为问题与语言解析非常相似。

我们能够在这种情况下,我们有3种不同的数据包类型的切片工作方法要解析?

最好的解决方法是什么?

由于提前,

+0

任何类型的解析器可能是这样的矫枉过正。你有*固定*宽度字段。 –

+0

@Kolyoly我编辑了这个问题。可以有不同类型的数据包。所以我想到了使用语法来解决这个问题。 – user2109788

回答

2

这样做,只是用切片这个工作:

def binParser(data): 
    result = {} 
    result["start"] = data[:2] 
    result["id"] = data[2:8] 
    result["end"] = data[-4:] 
    result["data"] = data[10:-4] 
    return result 

你会得到从字符串正确的数据。

+0

感谢您的回复。但是,对于这个问题,我甚至没有提到偶数领域是不固定的。用户将输入字段的长度作为语法的字段名称。多个字段也可以具有可变长度。 – user2109788

+1

@ user2109788:更多可变长度字段表示语法不明确。扩展你的问题。 –

+0

我已经延长了这个问题。在我的问题中,将只有一个可变长度字段。我一般都在想,所以我在上面的评论中提到可以有更多可变长度的字段。那么现在你能帮我找到问题的答案吗? – user2109788

2

大概只会有一个变长字段,所以你可以通过定义从序列的开始到结束的距离(例如,

rules = {'start': (None, 2), 'id': (2, 10), 
     'data': (10, -4), 'end': (-4, None)} 

然后用切片:

sequence = '1110110100110111011011110101100101100' 

result = dict((k, sequence[v[0]:v[1]]) for k, v in rules.items()) 

这给:

result == {'id': '10110100', 
      'end': '1100', 
      'data': '11011101101111010110010', 
      'start': '11'} 
+0

我们可以使用lambda来定义规则吗?我想通过内联呼叫设置规则。那可能吗? – JourneyMan

+0

我不确定你的意思。请举例输入和输出。 – jonrsharpe

1

既然你提到的标签pyparsing,这里是我怎么会去使用它pyparsing。这使用Daniel Sanchez的binParser进行后期处理。

from pyparsing import Word 

#Post-processing of the data. 
def binParser(m): 
    data = m[0] 
    return {'start':data[:2], 
      'id':data[2:8], 
      'end':data[-4:], 
      'data':data[10:-4]} 
#At least 14 character for the required fields, attaching the processor 
bin_sequence = Word('01',min=14).setParseAction(binParser) 


sequence = '1110110100110111011011110101100101100' 
print bin_sequence.parseString(sequence)[0] 

然后,这可以用作更大的解析器的一部分。