2016-09-08 4 views
3

非常に長い文字列を正規表現のマッチのためにスキャンしたい。最初のN正規表現を見つける最も効率的な方法は何でしょうか?例えば次のようなものがあります。Ruby:文字列中の最初のN個の正規表現を見つけて(スキャンを停止する)

'abcabcabc'.scan /b/, limit: 2 

は5文字以内で終了します。

(文字列は数MBである - メモリ内のメモ化データ構造 - これはウェブ要求であるパー​​フ事項。。)

+0

私はRegexpクラスのindexパラメータを開始する 'match'メソッドを使って、独自の' scan'関数を制限で実装するべきだと思います。 – nhahtdh

答えて

3

そのエレガントされないが、あなたはブロック形式を使用することができます。

str = 'abcabcabc' 

result = [] 
str.scan(/b/) { |match| result << match; break if result.size >= 2 } 
result #=> ["b", "b"] 
+1

Ruby 2.3.1のソースコードから、OPが望んでいることが分かります: 'while(!NIL_P(result = scan_once(str、pat、&start))){ last = prev; prev = start; rb_yield(結果); str_mod_check(str、p、len); } 'バージョンに依存している可能性もあります。 –

+0

@ NeeSlater文字列が完全にスキャンされる前に収穫が起こるようなブロック形式が「ストリーミング」されているとお考えですか? – mahemoff

+0

@mahemoffはい、これは非常に大きな文字列に対して上記を実行することで確認できます。 – Stefan

1

幸いにも、Rubyの正規表現はlazy matchingをサポートしていますので、あなたはこのようにそれを使用することができます:.*?を追加

'abcabcabc'.match(/(b).*?(b)/) 

がマッハます遅れて、正規表現が満たされるとすぐに停止します。 Regexp class repetition documentationから:

繰り返しはデフォルトでは欲張りです:できるだけ多くの出現が一致し、全体的な一致が成功するようにします。対照的に、遅延マッチングは、全体の成功に必要な最小限のマッチを行います。貪欲なメタキャラクターは、それに続いて怠け者にすることができます。

+0

はい、これは正規表現を作成するためにいくつかの計算でうまくいくかもしれません。例えば、 'multiples =#{regex} * limit;/* {multiples.join '。*?'}/' – mahemoff

関連する問題