1

Rails アプリケーションで動的な正規表現を作成したいと考えています。データベースで呼び出されるテーブルがありfooます。foo2 つの列で構成されておりidphraseこれは単に varchar(255) です。すべての「フレーズ」インスタンスが結合された 1 つの巨大な式を作成し、入力パラメーターがフレーズ内の単語のいずれかと一致するかどうかを確認できるようにしたいと考えています。以下のようにすればうまくいくのではないかと思ったのですが、うまくいきません。私は何を間違っていますか?

# get all phrases
phrases = Foo.all.map(&:phrase)

regex = Regexp.new phrases.join('|')

if params[:some_text] =~ regex
  # something in params[:some_text] matched at least one phrase
end
4

2 に答える 2

1

使用したいRegexp.union

ユニオン(pat1, pat2, ...) → new_regexp
ユニオン(pats_ary) → new_regexp

与えられたパターンの結合であるオブジェクトを返しRegexpます。つまり、その部分のいずれかに一致します。パターンはRegexpオブジェクトにすることができ、その場合、それらのオプションは保持されますString

だからこれだけ:

regex = Regexp.union(phrases)

例えば:

>> phrases = %w[pancakes egg$]
=> ["pancakes", "egg$"]
>> puts Regexp.new(phrases.join('|')).inspect
/pancakes|egg$/
>> puts Regexp.union(phrases).inspect
/pancakes|egg\$/

バージョンのエスケープ$に注意してください。特定の文字列を選択的にエスケープする必要がある場合は、(AKA )unionもあります。一般に、ランダムな文字列の束をマッシュアップして正規表現を構築したくはありません。正規表現の構文文字が毎回得られます。大きな交替に使用するか、ピースを組み立てる前に送信してください。Regexp.quoteRegexp.escapeRegex.unionRegex.escape

データベース内に保持したい場合は、LIKE クエリを実行することもできます。

Foo.where('phrase like ?', "%#{params[:some_text]}%")

または、すべてのパターンマッチングとそのエスケープの問題を完全にスキップして、単純な文字列位置チェックを実行します。

Foo.where('position(? in phrase) != 0', params[:some_text])

これらはどちらもテーブルスキャンを行いますが、Foo.all.

于 2012-11-13T23:55:02.270 に答える
-1
1.8.7 > phrases = ['one', 'two', 'three']
 => ["one", "two", "three"] 
1.8.7 > regex = Regexp.new phrases.join('|')
 => /one|two|three/ 
1.8.7 > puts 'match' if "a one b" =~ regex
match

おそらく他に何かが起こっているのでしょうか?あなたがしていることは私にとってはうまくいき、方程式からARを取り除きます.

于 2012-11-13T23:37:12.367 に答える