2017-02-10 6 views
0

私は正規表現エンジンに幾分類似したものを探していますが、結果が完全に重なり合うことができ、エンジンが一致を返す間に内部 "カーソル" 。正規表現エンジンと完全に重複した結果と "カーソル"操作

通常の正規表現の方法:item1|item2|item3、とあなたはすべての一致を得るためにfindallまたはfinditerいずれかを使用します。

は、さまざまな「選択肢」との正常な正規表現を持っていると言います。入力文字列内の特定の位置では、エンジンはこれらの選択肢のいずれかと一致する可能性があります。一度見つけられると、カーソルはマッチの終わりの直後にインデックスに進められ、選択肢のいずれかを探し続ける。これらの選択肢のうちの2つ以上が、初期のカーソルの位置に文字列にマッチしている可能性がある場合でも、一つだけが返されます。

import re 
input_string = 'foobar' 
compiled = re.compile('foobar|foo|bar') 
compiled.findall(input_string) 

# 'foobar' 

私は(1)欲しい:

私はそれらすべてになりたいです戻ってきた。そのような:

import muchneededregexthing 
input_string = 'foobar' 
compiled = muchneededregexthing.compile('foobar|foo|bar') 
searcher = compiled.create_searcher(input_string) 
while not searcher.reached_end(): 
    match = searcher.search() # increments searcher's internal cursor 
           # to after the end of the match 
    print(match.string, match.span()) 

# foobar (0,6) 
# foo (0,3) 
# bar (3,6) 

私も欲しい(2):私は、実行時に何が起こるかに応じて結果を操作できるように、検索者のカーソルを変更することができるようにしたい

(」 foob​​ar 'はマッチし、' foo 'と' bar 'は別々には関係ありません)。

  • str.find:私は、マークアップ(マークダウン/ウィキの/ etc)パーサのための正規表現の事を必要とする私は(おそらく)を使用することはできませんどのような

    import muchneededregexthing 
    input_string = 'foobarkitten' 
    compiled = muchneededregexthing.compile('foobar|foo|bar|kitten') 
    searcher = compiled.create_searcher(input_string) 
    while not searcher.reached_end(): 
        match = searcher.search() # increments searcher's internal cursor 
               # to after the end of the match 
        print(match.string, match.span()) 
        if match.string == 'foobar': 
         searcher.advance_cursor(match.end()) 
    
    # foobar (0,6) 
    # kitten (6,12) 
    

    。いつでも、多くの異なる要素を探す必要があります。 str.findを使用すると、マークアップがサポートするすべての要素でドキュメント全体を検索する必要があります。言語は

  • reなど、「ヘッダチャンク」、「段落チャンク」のような塊にドキュメントを細分化するには複雑すぎる:魔法の再、私は必要なものをサポートしていない限り、私は次の理由のためにそれを使用することはできません。正規表現あなたが好きなものにマッチすることはできません。しかし、その特性は私のような場合に有用です。私は2つの段階でマッチングを計画しています。正規表現は、要素の可能なマッチングを提供します。 可能なが一致するかどうかスマートな機能/方法が次に相談されますが一致します。そうなら、すばらしい、進んだカーソル。そうでない場合は、foobarをねじ込み、foobarにチャンスを与えます。

アイデアは大歓迎です。私はかなり機能が必要だと確信しています。これまでの私のベストプラクティスは、C/C++の大部分の正規表現構文をサポートしている自分自身のmuchneededregexthingモジュールを書くことです。だから私はあなたのアイデアを遠くから奪ってしまうことを恐れることはありません。

編集1:マークアップの例えば要求:

マークアップ要素と一致する必要がある、従ってトークンは、定義され、プラグインにより持ち込まれます。したがって、フレームワークにはマークアップが含まれていません。私は単にプラグインのトークンを正規表現にマッチさせてやることができますが、少なくともオプションを調べて、正規表現でサポートできるものよりも広い範囲のマークアップトークンを許可したいと思います。たとえば、数値が文字列の数値表現でなければならない場合、どのように一致するでしょうか?string:numbera:0は有効なトークンですが、a:1は有効ではありません。ただしb:1bc:28(1 * 26 + 2 * 1)です。

この例では、プラグインは([a-z]{1,5})([0-9]{1,5})のような正規表現を提供できます。アルゴリズムは、第1のグループの数値を計算し、第2のグループの値と比較する特殊関数に一致を渡す。これらの値が一致する場合、プラグインはドキュメントのこの部分を処理します。そうでない場合は、それが返され、別のプラグインがドキュメント内でこのインデックスを処理しようとします。

+0

重複マッチングのデフォルトの動作は、各マッチ後にカーソルを1つの位置に進めることです。少なくとも1つの位置を前進させることができない場合、無限ループに入ります。正規表現は固定されています。例 '(?=(o + | foo))'の文字列 'fooooo'には5つのマッチがあります。また、一度に1つの文字がある位置に存在するので、正規表現だけが可変である可能性があります。つまり_item_'X'は_X_のみで、Yは決してできません。しかし、正規表現は状態に固定されているので変わらないでしょう。従って、位置の前進。 – sln

+0

複数の正規表現を使って1つの位置をスキャンすることもできます。しかし、あなたは正規表現を設定し、文字列内の位置を設定することによってそれを制御する必要があります。これは単一のアクションです。 – sln

+0

あなたのマークダウンの例を挙げることができますか?おそらく、正規表現や再帰的な構文解析によって解くことができます。 – fafl

答えて

0

純粋なPythonで簡単に実装できます。同じ長さの同じ場所に2つの異なるパターンが一致しないことが保証されている場合は、簡単に実装できます。

patternがコンパイルされた正規表現であれば、pattern.search(str, start)length最大で長さのstartで始まるマッチを探しますstartpattern.search(str, start, length)から始まるマッチを探します。

だから、検索してください。一致した場所に進む。それが欲しいかどうかを確認してください。そうでない場合は、それを放棄することを決定します。同じパターンと短い長さの同じ点で別の検索を行います。一致しない場合、またはそれ以上一致する場合は、カーソルを進めます。

+0

公正なポイントですが、それらのパターンの長さがすべて異なるという保証はありません。また、これは注文の制限(最長のパターンが最初)を課すのに対し、私はむしろ要素の優先順位に従ってパターンを並べ替えるでしょう(見出しは段落よりも優先順位が高いため、見出しのパターンが最初になります)。 – delins