5

これは非常に単純になりますが、次の 2 つのパターンのいずれかに一致させようとしています。

"GET /ligonier-broadcast-media/mp3/rym20110421.mp3 HTTP/1.1"

また

-

私はこのようなことを試しました:

key = Word(alphas + nums + "/" + "-" + "_" + "." + "?" + "=" + "%" + "&")

uri = Or("-" | Group(
                   Suppress("\"") +
                   http_method +
                   key.setResultsName("request_uri") +
                   http_protocol +
                   Suppress("\"")
               )
      )

でも似合わないらしい。Or() を使用する方法、Group() を使用する必要がある場合、または何を行うべきか、まったくわかりません。Group() クラス内で提供される引数が個別に呼び出された場合に機能することはわかっていますが、1 つだけではなく、ダッシュまたは引用符で囲まれた URI 文字列が本当に必要です。

ログ形式はネゴシエートできません。与えられたものを消費しています。どんなヒントでも大歓迎です。

4

2 に答える 2

19

一般に、Or、And、MatchFirst、および Each クラスが pyparse で公然と使用されることはほとんどありません。推奨されるスタイルは、類似した演算子のオーバーロードを使用することです。あなたの場合、両方のフォームを使用していますが、邪魔になっています。

少しクリーンアップした後の式は次のとおりです。

key = Word(alphanums + "/-_.?=%&")
QUOT = Suppress('"')
uri = ("-" | QUOT
             + http_method
             + key("request_uri")
             + http_protocol
             + QUOT
      )

Word への引数は、許可された文字のセットを表す文字列です。(あなたの場合のように)引数が1つだけ使用されている場合、文字列は単にWordの一部として解析できる文字のセットとして解釈されます。2 つの文字列が指定されている場合、最初の文字列は受け入れ可能な先頭文字のセットを表し、2 番目は受け入れ可能な本文文字のセットを表します (変数名のようなものを定義する場合に便利です。たとえば、Python ではアルファと '_' のみが許可されます)。先頭の文字だけでなく、本文に数字を使用することもできます. これWord(alphas+'_', alphanums+'_')"/" + "-" + "_" + ....

「|」演算子は、許可された選択肢を区切り、MatchFirst 式を生成します。パーサーは、最初に指定された式が一致した後に試行を停止するため、MatchFirst と呼ばれます。したがって、文字列 "abc" を で解析する場合Word(alphas) | Word(nums)、pyparsing はWord(nums)式の照合さえ試みません - 最初の代替が一致します。必要なものに重複がある場合、これはさらに難しくなります。文字の単語、アルファベットの単語、または文字とアルファベットの単語を照合し、文字列 "abc123" を解析したいとします。このパーサー:

Word(alphas) | Word(nums) | Word(alphanums)

文字列の先頭の 'abc' を先頭のWord(alphas). 多くの場合、次のような代替案を再配置することで、このような問題を解決できます。

Word(alphanums) | Word(alphas) | Word(nums)

しかし、すべてのケースがそれほど簡単にリファクタリングできるわけではありません。そのため、pyparsing は、'^' 演算子を使用して定義された Or 式もサポートします ('^' は、長さを測定するための製図工の仕切りのペアを思い起こさせるため、これを選択しました)。Or 式は、指定されたすべての選択肢を適用しようとし、最も長く一致する選択肢を選択します。したがって、私の小さなテスト例を次のように書くことができます。

Word(alphas) ^ Word(nums) ^ Word(alphanums)

これで、"abc" に一致するときに pyparse は停止しませんが、すべての選択肢を試し、最終的に "abc123" に一致する 3 番目の選択肢を選択します。

URI 定義については、Or マッチングを行う必要はありません。パーサーが先頭の「-」と引用符で囲まれた HTTP コマンド文字列を混同することはありません。したがって、「|」を使用して行った MatchFirst を使用します。演算子は、完全に適切です。

その他のアイテム:

  • "\""できることなら、Python で書かないでください。Python は、まさにこの理由で両方の引用符をサポートしています。'"'代わりに使用してください。バックスラッシュは、C プログラマーおよび Windows ファイル名用です。

  • expr.setResultsName("name")expr("name")pyparsing 1.4.6 以降に簡略化されました。短縮された構文は、パーサー定義の可読性に非常に役立ちます。

  • 結果に何らかの構造を保持したい場合、または結果名を持つ内部表現を持つ繰り返し構造がある場合にのみ、グループを使用してください。パーサーには実際には必要ありません。結果に別のリスト コンテナー ラッパーを追加するだけで[0]、解析されたデータにアクセスするために追加のインデックスが必要になります。

( 、 などを明示的に呼び出すことにした場合は、必ず式のリストを渡し、それらを式コンストラクターへの引数としてリストするだけではありません -私の使用のために pyparsing で順序付けられた選択が失敗する理由を参照してくださいそのようなタイプミスがどのように物事を混乱させる可能性があるかについては、算術演算子を使用してパーサーを構成することをお勧めします.)OrAnd

于 2011-04-27T10:32:14.937 に答える
1

私はあなたが欲しいと思います...

from pyparsing import oneOf
# more code here
uri = oneOf(["-", <insert long match expr here>])`
uri.matchString(someStringVar)
于 2011-04-27T03:55:35.400 に答える