PyParsingで本当に単純なものを複数行で解析しようとしていますが、なぜ動作しないのか分かりません。解析したい文字列は以下の通りです。複数行のPyParsingの例
string = '''START
1 10; % Name1
2 20; % Name2
END'''
私は、STARTとENDトークン間のすべての行がint
またはfloat
タイプすることができる1つまたはそれ以上の正/負の数値が含まれていることを知っています。私はまた、ユーザが%
符号の後に追加のメタデータを任意に追加することを期待しています。
フロートと名前の基本的な文法を定義することから始めます。
Float = Word(nums + '.' + '-')
Name = Word(alphanums)
Iは、ラインがセミコロンに続く一つ以上Float
を含み、任意に% Name
によってできることを知っています。
Line = OneOrMore(Float)('data') + Suppress(Literal(';')) + Suppress(Optional(Literal('%'))) + Optional(OneOrMore(Name)('name')) + Suppress(LineEnd())
多くの行が必要なので、次のように行の文法を定義できます。ポールにより示唆されるように、私は可能取り出すにするためにthis answerでGroup
を使用
Lines = OneOrMore(Group(Line))
。
grammar = Suppress(Keyword('START')) + Lines + Suppress(Keyword('END'))
grammar.parseString(string)
しかし、これは簡単にコピー&ペーストについては、以下の次
ParseException: Expected end of line (at char 62), (line:3, col:19)
完全なコードをというエラーがスローされます。
string = '''START
1 10; % Name1
2 20; % Name2
END'''
from pyparsing import Word, Keyword, nums, OneOrMore, Optional, Suppress, Literal, alphanums, LineEnd, LineStart, Group
Float = Word(nums + '.' + '-')
Name = Word(alphanums)
Line = OneOrMore(Float)('data') + Suppress(Literal(';')) + Suppress(Optional(Literal('%'))) + Optional(OneOrMore(Name)('name')) + Suppress(LineEnd())
Lines = OneOrMore(Group(Line))
grammar = Suppress(Keyword('START')) + Lines + Suppress(Keyword('END'))
grammar.parseString(string)
編集:私はどちらか無駄に以下のことを試してみた
。
string = '''START
1 10; % Name1
2 20; % Name2
END'''
from pyparsing import Word, Keyword, nums, OneOrMore, Optional, Suppress, Literal, alphanums, LineEnd, LineStart, Group
Float = Word(nums + '.' + '-')
Name = Word(alphanums)
NL = Suppress(LineEnd())
Line = OneOrMore(Float)('data') + Suppress(Literal(';')) + Optional(~NL +
Suppress(Literal('%'))
+ OneOrMore(Name)('name') + NL) | NL
Lines = OneOrMore(Group(Line))
grammar = Suppress(Keyword('START')) + Lines + Suppress(Keyword('END'))
grammar.parseString(string)
動作するようには思えない唯一のことは、私はrestOfLine
Line = OneOrMore(Float)('data') + Suppress(Literal(';')) + Optional(restOfLine)
を使用している場合ただし、これは構造化された形式でセミコロンの後の部分を返さないと、私はそれを解析する必要があります別にもう一度。これが推奨されるアプローチですか?
"Name.setDebug()"と "Float.setDebug()"を追加し、その出力が役立つかどうかを確認してください。 – PaulMcG
その出力は 'OneOrMore(Name)'が行末より先に進んでいることを示唆しているようです。 OneOrMore(Name)が行末で停止することを確認するには、どのような方法が推奨されますか。私はOneOrMore(Name)+ NLを試しましたが、どちらもうまくいきませんでした。理由を理解できませんでした。 – kdheepak
まず、 "2"は有効な名前ですか?第二に、あなたの文法では行末が重要ですか?その場合は、ParserElement.setDefaultWhitespaceChars(https://pythonhosted.org/pyparsing/pyparsing.ParserElement-class.html#setDefaultWhitespaceCharsのdocsのサンプルインラインを参照)を使用して、無視できる空白のセットからそれらを削除する必要があります。最後に、フロートと名前の定義を強化することができます。今のところ、「...」、「---」、「1.1」などの文字列と一致します。1 "、Nameは" 12345 "と" 221B "に一致します – PaulMcG