2012-03-19 14 views
4

ストリームに適用されるre.findall、またはより良い意味では、re.finditerの機能を利用する方法はありますか(つまり、読み取り用のファイルハンドルを開いていますか)。ストリーム上のfindall/finditer?

ではなく、です。一致するパターンが1行の入力内に完全に含まれている(つまり、複数行のパターンが許可されている)と仮定します。また、最大一致長を想定していません。

この一般性のレベルでは、正規表現エンジンが文字列全体にアクセスする必要がある正規表現を指定することは可能です(例:r'(?sm).*')。もちろん、ファイル全体をメモリに保存しますが、現時点ではこの最悪のシナリオには関心がありません。結局、ではないがメモリにファイル全体を読むことを必要とする複数行一致の正規表現を書くことは完全に可能です。

コンパイル済みの正規表現から基本となるオートマトン(または内部的に使用されているもの)にアクセスして文字ストリームにすることはできますか?

ありがとうございます!

編集:Tim Pietzckerとrplntの回答に応じて、複数行のパターンと一致する長さに関する説明が追加されました。

+0

編集ありがとうございます - 私は私の答えを更新しました。 –

答えて

3

これは、正規表現の一致が改行に及ばないことがわかっている場合に可能です。

その後、あなたは単にマッチが複数行にまたがることができれば、あなたはファイル全体をメモリに読み込む必要があり

for line in file: 
    result = re.finditer(regex, line) 
    # do something... 

を行うことができます。それ以外の場合は、あなたの試合がすでに行われているかどうか、さらに先にコンテンツが先に試合が不可能になった場合、またはファイルが十分に読み込まれていないために試合がうまくいかない場合はどうなりますか?

編集:

理論的には、これを行うことが可能です。正規表現エンジンは、試合中にストリームの現在読み込まれている部分の終わりに到達するかどうかを調べなければならないかどうかを調べなければなりません。しかし、Pythonエンジンはこれをしません。

編集2:

私は、PythonのSTDLIBのre.pyとその関連モジュールを見て撮影しました。 .match()メソッドなどの正規表現オブジェクトの実際の生成は、C拡張で行われます。したがって、Cソースを直接編集して独自のPythonバージョンをビルドしない限り、ストリームにも対応してアクセスすることはできません。

2

既知の最大長のregexpで実装することは可能です。 +/*または最大反復回数を知っているもの。これを知っていれば、チャンクでファイルを読み込み、これらを照合して結果を得ることができます。また、正規表現が一致しても文字列の終わりで停止したときに、大文字と小文字を重複するチャンクで実行することになります。

いくつかの擬似(のpython)コード:

overlap_tail = '' 
matched = {} 
for chunk in file.stream(chunk_size): 
    # calculate chunk_start 
    for result in finditer(match, overlap_tail+chunk): 
     if not chunk_start + result.start() in matched: 
      yield result 
      matched[chunk_start + result.start()] = result 
    # delete old results from dict 
    overlap_tail = chunk[-max_re_len:] 

ジャストアイデアが、私はあなたが私が達成しようとしているものを得る願っています。ファイル(ストリーム)が終了する可能性があり、それ以外の場合があると考える必要があります。しかし、私はそれができると思う(正規表現の長さが限られている(知られている)場合)。

関連する問題