【发布时间】:2013-02-07 01:11:37
【问题描述】:
我被困住了。几天来一直试图解析这个文本(看底部)。但是有些事情想不通。首先,文本被格式化为具有固定宽度列的树结构,但确切的列宽取决于最宽的字段。
我正在使用 ruby,首先我尝试了 Treetop gem 并取得了一些进展,但后来决定尝试 Parslet,所以我现在正在使用它,它似乎应该更容易使用,但很难找到它的详细文档.
目前我单独解析每一行并创建带有解析条目的数组,但这不正确,因为我松散了结构。我需要递归解析它并处理深度。
我非常感谢任何提示、想法和建议。
这是我当前的代码,它可以工作,但所有数据都被展平了。我目前的想法是递归解析当前行的起始位置是否大于以前的行起始位置(即宽度),因此这意味着我们应该进入更深层次。实际上我设法做到了,但后来我无法正常出门,所以我删除了该代码。
require 'pp'
require 'parslet'
require 'parslet/convenience'
class TextParser < Parslet::Parser
@@width = 5
root :text
rule(:text) { (line >> newline).repeat }
rule(:line) { left >> ( topline | subline ).as(:entry) }
rule(:topline) {
float.as(:number) >> str('%') >> space >> somestring.as(:string1) >> space >> specialstring.as(:string2) >> space >> specialstring.as(:string3)
}
rule(:subline) {
dynamic { |source, context|
width = context.captures[:width].to_s.length
width = width-1 if context.captures[:width].to_s[-1] == '|'
if width > @@width
# should be recursive
result = ( specialline | lastline | otherline | empty )
else
result = ( specialline | lastline | otherline | empty )
end
@@width = width
result
}
}
rule(:otherline) {
somestring.as(:string1)
}
rule(:specialline) {
float.as(:number) >> str('%') >> dash >> space? >> specialstring.as(:string1)
}
rule(:lastline) {
float.as(:number) >> str('%') >> dash >> space? >> str('[...]')
}
rule(:empty) {
space?
}
rule(:left) { seperator.capture(:width) >> dash?.capture(:dash) >> space? }
rule(:somestring) { match['0-9A-Za-z\.\-'].repeat(1) }
rule(:specialstring) { match['0-9A-Za-z&()*,\.:<>_~'].repeat(1) }
rule(:space) { match('[ \t]').repeat(1) }
rule(:space?) { space.maybe }
rule(:newline) { space? >> match('[\r\n]').repeat(1) }
rule(:seperator) { space >> (str('|') >> space?).repeat }
rule(:dash) { space? >> str('-').repeat(1) }
rule(:dash?) { dash.maybe }
rule(:float) { (digits >> str('.') >> digits) }
rule(:digits) { match['0-9'].repeat(1) }
end
parser = TextParser.new
file = File.open("text.txt", "rb")
contents = file.read.to_s
file.close
pp parser.parse_with_debug(contents)
文字看起来像这样 (https://gist.github.com/davispuh/4726538)
1.23% somestring specialstring specialstring
|
--- specialstring
|
|--12.34%-- specialstring
| specialstring
| |
| |--12.34%-- specialstring
| | specialstring
| | |
| | |--12.34%-- specialstring
| | --1.12%-- [...]
| |
| --2.23%-- specialstring
| |
| |--12.34%-- specialstring
| | specialstring
| | specialstring
| | |
| | |--12.34%-- specialstring
| | | specialstring
| | | specialstring
| | --1.23%-- [...]
| |
| --1.23%-- [...]
|
--1.05%-- [...]
1.23% somestring specialstring specialstring
2.34% somestring specialstring specialstring
|
--- specialstring
specialstring
specialstring
|
|--23.34%-- specialstring
| specialstring
| specialstring
--34.56%-- [...]
|
--- specialstring
specialstring
|
|--12.34%-- specialstring
| |
| |--100.00%-- specialstring
| | specialstring
| --0.00%-- [...]
--23.34%-- [...]
谢谢:)
【问题讨论】:
-
是什么生成了该文本,它是否有其他输出数据的方式?您显示并尝试解析的输出并不是真正为解析而设计的。相反,它是为了帮助可视化某些东西。这对人眼来说很好,但对于数据重用来说很糟糕。
-
反对什么?我看不出这个问题有什么不好。
-
没错,这就是为什么我需要解析它,但遗憾的是我无法获得任何其他输出:(
-
你还没有说是什么生成了那个文件。另外,它从哪里获取数据?
-
查看“perf tutorial”,似乎还有其他更易读的方式来输出数据,尤其是“Machine Readable Output”。我没有玩过它,但它似乎是一个更容易的路径。
标签: ruby parsing text abstract-syntax-tree parslet