2013-03-20 3 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 개의 요소가 포함됩니다. 값이 정의되지 않으면 0입니다.

구조 이름과 요소 값을 추출하는 가장 우아한 방법은 무엇입니까? 압축을 풀면 빠르고 쉽게 액세스 할 수 있도록 사전에 저장됩니다.

정규식을 사용해 보았지만이 특정 문제에 대한 매우 효율적인 해결책이 아닙니다. 이와 같은 것을 해결하기 위해 일반적으로 어떤 접근법이 사용됩니까? ,이 같은 것을 사용할 수 있습니다 STRUCT 및 수동으로 분석 할 (당신이 그것을 할 때주의) :

답변

3

이 코드는 알골 모양의 중괄호 (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를 추출 할 경우)

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]]) 

제안을 : 구문 분석 할 때 정규식을 피하려고합니다.

관련 문제