我想在我的Rails应用程序中创建一个动态正则表达式。我的数据库中有一个名为foo
的表。 foo
由两列id
和phrase
组成,它们只是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
答案 0 :(得分:1)
您想使用Regexp.union
:
union(pat1,pat2,...)→new_regexp
union(pats_ary)→new_regexp返回一个
Regexp
对象,它是给定模式的并集,即匹配其任何部分。模式可以是Regexp
个对象,在这种情况下,它们的选项将被保留,或String
s。
所以就这样:
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
也是如此。
答案 1 :(得分:-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。