我有一个使用空格构建的大型源代码文件。我只对结构化文本文件的一个特定部分感兴趣,如下所示:
SP : STRUCT
Spare : STRUCT //Spare
Val : INT := 100;
UpLim : INT := 100;
LoLim : INT ;
Def : INT := 100;
Prot : INT := 2;
END_STRUCT ;
END_STRUCT ;
如您所见,定义了一个'SP'结构(这些结构将在整个源代码中点缀,但具有相同的名称),其中包含一个或多个相同类型的其他结构。在这个例子中只有一个叫做“Spare”。每个结构将始终包含相同的5个元素。如果没有定义值,则为零。
提取结构名称及其元素值的最优雅方法是什么?提取后,它们将存储在字典中,以便快速方便地访问。
我尝试过使用正则表达式,但我不确定这是解决这一特定问题的非常有效的方法。通常采取什么方法来解决这样的问题?
答案 0 :(得分: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 :(得分: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]])
建议:在解析时尽量避免使用正则表达式。