1

我想在我的 Rails 应用程序中创建一个动态正则表达式。我的数据库中有一个名为的表foofoo由两列组成,idphrase只是 varchar(255)。我希望能够制作一个包含所有“短语”实例的巨型表达式,并查看传入参数是否与短语中的任何单词匹配。我认为像下面这样的东西可能会做到这一点,但它似乎不能正常工作。我究竟做错了什么?

# 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

union(pat1, pat2, ...) → new_regexp
union(pats_ary) → new_regexp

返回一个Regexp对象,它是给定模式的联合,即,将匹配其任何部分。模式可以是Regexp对象,在这种情况下,它们的选项将被保留,或者Strings.

所以就这样:

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\$/

$注意版本中的转义union。如果您需要有选择地转义特定字符串,还有Regexp.quote(AKA )。Regexp.escape通常,您不想只是将一堆随机字符串混合在一起来构建正则表达式,正则表达式语法字符每次都会让您受益;用于Regex.union大交替或Regex.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 回答