2014-02-18 86 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] 

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