2013-03-20 23 views
0

我有一個使用空格結構的大型源代碼文件。我只是在結構化文本文件的一個特定部分,它看起來像這樣有興趣:從空間縮進結構化文件中有效地提取文本塊

SP : STRUCT 
    Spare : STRUCT //Spare 
    Val : INT := 100; 
    UpLim : INT := 100; 
    LoLim : INT ; 
    Def : INT := 100; 
    Prot : INT := 2; 
    END_STRUCT ;  
    END_STRUCT ; 

正如你可以看到,有一個定義的「SP」結構(這將在整個源代碼加以點綴,但具有相同的名稱),其中包含一個或多個相同類型的其他結構。在這個例子中,只有一個叫做'備用'。每個結構將始終包含相同的5個元素。如果沒有定義值,則爲零。

提取結構名稱及其元素值的最優雅方式是什麼?一旦提取出來,它們將被存儲在字典中以便快速和容易地訪問。

我試過使用正則表達式,但我不太確定這是一個非常有效的解決方案,這個特定的問題。通常採取什麼辦法來解決這樣的問題?

回答

3

此代碼似乎使用algol樣大括號(struct/end_struct)。我不認爲縮進在語法上很重要。因此解析器應該是基於關鍵字的,例如:

import re 

def parse(data): 
    stack = [{}] 

    for x in data.splitlines(): 
     x = re.sub(r'\s+', '', x) 

     m = re.match(r'(\w+):STRUCT', x) 
     if m: 
      d = {} 
      stack[-1][m.group(1)] = d 
      stack.append(d) 
      continue 

     m = re.match(r'(\w+):INT(?::=(\w+))?', x) 
     if m: 
      stack[-1][m.group(1)] = int(m.group(2) or 0) 
      continue 

     m = re.match(r'END_STRUCT', x) 
     if m: 
      stack.pop() 
      continue 

    return stack[0] 

結果:

data = """ 
    SP : STRUCT 
    Spare : STRUCT //Spare 
    Val : INT := 100; 
    UpLim : INT := 100; 
    LoLim : INT ; 
    Def : INT := 100; 
    Prot : INT := 2; 
    END_STRUCT ;  
    END_STRUCT ; 
""" 

print parse(data) 
# {'SP': {'Spare': {'LoLim': 0, 'Prot': 2, 'Def': 100, 'UpLim': 100, 'Val': 100}}} 
1

如果你想只提取SP:struct和你想手動解析它(注意,當你這樣做),你可以使用這樣的事情:

data = {} 
found = False 
with open("code.txt", "r") as code: 
    for line in code.readline(): 
     clean = line.split("//")[0].strip().rstrip(";").split(":") 
     fields = map(lambda f: f.strip(), clean) 
     if found and fields[0].upper() == "END_STRUCT": 
      break 
     elif len(fields) == 2: 
      if fields[0].upper() == "SP" and fields[1].upper() == "STRUCT": 
       found = True 
     elif len(fields) == 3 and found: 
      if fields[1].upper() != "STRUCT": 
       data[fields[0]] = fields[2].lstrip("=").strip() 

我用.upper()和爲了安全起見,我檢查了len(字段),而我使用.strip()主要是爲了忽略縮進(這看起來不需要:代碼在沒有它的情況下可以是有效的)。

您還可以添加這段代碼(在最後一行的同一縮進級別)來存儲在正確格式的信息:

if fields[1].upper() == "INT": 
    data[fields[0]] = int(data[fields[2]]) 
#elif field[1].upper == "SOMETHING_ELSE": 
# data[fields[0]] = convert(data[fields[2]]) 

建議:儘量避免正則表達式解析時。

相關問題