我有一个包含大量数据的文件,其格式与此类似:
Group1 {
Entry1 {
Title1 [{Data1:Member1, Data2:Member2}]
Title2 [{Data3:Member3, Data4:Member4}]
}
Entry2 {
...
}
}
Group2 {
DifferentEntry1 {
DiffTitle1 {
...
}
}
}
事实是,我不知道有多少层括号,以及数据的结构。我需要修改数据,并在将所有内容写入新文件之前,根据涉及数据成员的条件删除整个“条目”。在这样的文件中阅读的最佳方式是什么?谢谢!
答案 0 :(得分:3)
数据结构基本上似乎是一个字典,它们的键是字符串,值是一个字符串或同一类型的另一个字典,所以我建议把它拉成那种python结构,
例如:
{'group1': {'Entry2': {}, 'Entry1': {'Title1':{'Data4': 'Member4',
'Data1': 'Member1','Data3': 'Member3', 'Data2': 'Member2'},
'Title2': {}}}
在文件的顶层,您将创建一个空白字典,然后对于您阅读的每一行,您使用标识符作为键,然后当您看到{您创建该键的值作为字典时。当您看到Key:Value时,您只需正常插入值,而不是将该键创建为dict。当你看到一个}你必须'回到'上一个词典时,你正在努力并回去填补它。
我认为整个解析器将文件放入这样的python结构中可以在一个相当短的递归函数中完成,当它看到{然后返回到它时,它只是调用自己来填充每个子字典看见时打电话
答案 1 :(得分:3)
这是一个语法。
dict_content : NAME ':' NAME [ ',' dict_content ]?
| NAME '{' [ dict_content ]? '}' [ dict_content ]?
| NAME '[' [ list_content ]? ']' [ dict_content ]?
;
list_content : NAME [ ',' list_content ]?
| '{' [ dict_content ]? '}' [ ',' list_content ]?
| '[' [ list_content ]? ']' [ ',' list_content ]?
;
最高级别为dict_content
。
我对列表中嵌入的词组和列表之后的逗号有点不确定,因为您没有提供任何示例。
答案 2 :(得分:2)
如果你有数据文件结构的语法,或者你可以自己创建它,你可以使用Python的解析器生成器,比如YAPPS:link text。
答案 3 :(得分:1)
这取决于数据的结构,以及您需要做哪些更改。
一个选项可能是将其解析为Python数据结构,它看起来很相似,除了你没有字符串的引号。这使得复杂的操作变得容易。
另一方面,如果您只需进行更改以将某些条目修改为其他条目,则可以通过搜索和替换来执行此操作。
因此,在了解最佳方法之前,您需要更好地了解问题。
答案 4 :(得分:1)
这是一个与XML处理非常相似的问题,并且有很多Python代码可以做到这一点。因此,如果您能以某种方式将文件转换为XML,则可以通过标准库中的解析器运行它。您的示例的XML版本将是这样的:
<group id="Group1">
<entry id="Entry1">
<title id="Title1"><data id="Data1">Member1</data> <data id="Data2">Member2</data></title>
<title id="Title2"><data id="Data3">Member3</data> <data id="Data4">Member4</data></title>
</entry>
<entry id="Entry2">
...
</entry>
</group>
当然,转换为XML可能不是最简单的事情。但是你的工作与XML解析器已经完成的工作非常类似,你只需要处理不同的语法。因此,您可以查看一些XML解析代码,并基于此为您的数据文件编写一些Python解析器。 (根据XML解析器的实现方式,您甚至可以复制代码,只需更改一些正则表达式,然后为您的文件运行它)
答案 5 :(得分:1)
我有类似的东西,但用java编写。它解析具有相同基本结构的文件,语法略有不同(没有'{'和'}'只有缩进,就像在python中一样)。这是一种非常简单的脚本语言。
基本上它的工作原理如下:它使用堆栈来跟踪最内部的指令块(或者在你的情况下是数据),并将每个新指令附加到顶部的块上。如果它解析一个需要新块的指令,则将其推送到堆栈。如果一个块结束,它会从堆栈中弹出一个元素。
我不想发布整个来源,因为它很大并且可以在谷歌代码上使用(lizzard-entertainment,修订版405)。您需要了解一些事项。
占位符
BufferedReader input = null;
try {
input = new BufferedReader(new FileReader(inputFileName));
// Stack of instruction blocks
Stack<Block> stack = new Stack<Block>();
// Push the root block
stack.push(this.topLevelBlock);
String line = null;
Instruction prev = new Noop();
while ((line = input.readLine()) != null) {
// Difference between the indentation of the previous and this line
// You do not need this you will be using {} to specify block boundaries
int level = indent_level(line) - stack.size();
// Parse the line (returns an instruction object)
Instruction inst = Instruction.parse(line.trim().split(" +"));
// If the previous instruction expects a block (for example repeat)
if (prev.block_expected()) {
if (level != 1) {
// TODO handle error
continue;
}
// Push the previous instruction and add the current instruction
stack.push((Block)(prev));
stack.peek().add(inst);
} else {
if (level > 0) {
// TODO handle error
continue;
} else if (level < 0) {
// Pop the stack at the end of blocks
for (int i = 0; i < -level; ++i)
stack.pop();
}
stack.peek().add(inst);
}
prev = inst;
}
} finally {
if (input != null)
input.close();
}