我在普通正则表达式中创建了这个正则表达式
/(first|last)\s(last|first)/i
它匹配前三个
first last
Last first
First Last
First name
我正在尝试获取full_name
与我编写的正则表达式匹配的所有记录。我正在使用PostgreSQL
Person.where("full_name ILIKE ?", "%(first|last)%(last|first)%")
这是我的尝试。我还尝试了SIMILAR TO
和~
没有运气
答案 0 :(得分:39)
您的LIKE查询:
full_name ilike '%(first|last)%(last|first)%'
不起作用,因为LIKE不理解正则表达式分组((...)
)或替换(|
),LIKE只能理解单个字符的_
(如正则表达式中的.
和%
任意零个或多个字符的序列(如正则表达式中的.*
)。
如果您将该模式交给SIMILAR TO,那么您会发现'first last'
,但由于案例问题,其他人都没有;但是,这个:
lower(full_name) similar to '%(first|last)%(last|first)%'
将处理案例问题并找到与正则表达式相同的内容。
如果你想使用一个正则表达式(你可能会这样做,因为LIKE是非常有限和繁琐的,而且类似于某些SQL标准小组委员会的狂热思想的奇怪产品)那么你会想要使用不区分大小写的匹配运算符和原始正则表达式:
full_name ~* '(first|last)\s+(last|first)'
这转化为AR的这一点:
Person.where('full_name ~* :pat', :pat => '(first|last)\s+(last|first)')
# or this
Person.where('full_name ~* ?', '(first|last)\s+(last|first)')
我的代码中有一个微妙的变化需要注意:我使用单引号作为我的Ruby字符串,你使用的是双引号。反斜杠在双引号字符串中比在单引号字符串中表示更多,因此'\s'
和"\s"
是不同的东西。抛出几个to_sql
电话,你可能会看到一些有趣的东西:
> puts Person.where('full_name ~* :pat', :pat => 'a\s+b').to_sql
SELECT "people".* FROM "people" WHERE (full_name ~* 'a\s+b')
> puts Person.where('full_name ~* :pat', :pat => "a\s+b").to_sql
SELECT "people".* FROM "people" WHERE (full_name ~* 'a +b')
这种差异可能不会导致任何问题,但是当每个人都想使用相同的转义字符时,你需要非常小心你的字符串。就个人而言,我使用单引号字符串,除非我特别需要双引号字符串的额外转义和字符串插值功能。