1

私は立ち往生しています。数日間、このテキストを解析しようとしていました(下部を見てください)。しかし、いくつかのことを理解することはできません。まず、テキストは固定幅の列を持つツリー構造でフォーマットされますが、正確な列幅は最も広いフィールドによって異なります。

私は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%-- [...]

ありがとう :)

4

1 に答える 1

2

「ブリキの木こり」と同じことを言うつもりでした。データを生成できる別の形式が必要です。

ただし、これを解析したい場合は...Parsletはmap/reduceアルゴリズムのように機能します。最初のパス(解析)は、ソースドキュメントから必要なすべての情報をキャプチャするためだけに、最終的な出力を提供することを目的としたものではありません。

それをツリーに保存したら、それを変換して必要な出力を取得できます。

だから...私は、各空白をノードとして記録し、必要なテキストとパーセンテージを一致させるパーサーを作成します。空白ノードを「インデント」ノードにグループ化します。

次に、変換を使用して空白ノードをノードの数に置き換え、インデントを計算します。

注意:Parsletは標準のルビーハッシュを生成します。次に、このツリーを理解するために好きなコードを書くことができます。

パーサーは、テキストファイルを操作可能なデータ構造に変換するだけです。

繰り返しになりますが。「TheTinMan」が正しい答えだと思います。代わりに、機械で読み取り可能な方法でデータを生成します。

アップデート:

別のアプローチについては、以下を確認できます。RubyでParsletを使用するインデントに敏感なパーサー?

于 2013-02-10T13:51:05.663 に答える