高效提取空格缩进结构文件中的文本块
我有一个很大的源代码文件,这个文件是用空格来组织结构的。我只对文件中特定的一部分内容感兴趣,内容大概是这样的:
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个元素。如果没有定义值,那就是零。
我想知道,提取这个结构的名字和它的元素值的最优雅的方法是什么?提取出来后,我会把它们存储在一个字典里,这样可以快速方便地访问。
我试过用正则表达式,但不太确定这对这个特定问题是否是个高效的解决方案。通常解决这种问题会采取什么方法呢?
2 个回答
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(fields)),这是出于安全考虑。同时,我用了 .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]])
建议:在解析的时候尽量避免使用正则表达式。
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}}}