Ruby on rails 在ruby中使用正则表达式拆分数据库查询字符串
我有一个要分离出来的查询字符串Ruby on rails 在ruby中使用正则表达式拆分数据库查询字符串,ruby-on-rails,regex,ruby,Ruby On Rails,Regex,Ruby,我有一个要分离出来的查询字符串 created_at BETWEEN '2018-01-01T00:00:00+05:30' AND '2019-01-01T00:00:00+05:30' AND updated_at BETWEEN '2018-05-01T00:00:00+05:30' AND '2019-05-01T00:00:00+05:30' AND user_id = 5 AND status = 'closed' 像这样 created_at BETWEEN '2018-01-
created_at BETWEEN '2018-01-01T00:00:00+05:30' AND '2019-01-01T00:00:00+05:30' AND updated_at BETWEEN '2018-05-01T00:00:00+05:30' AND '2019-05-01T00:00:00+05:30' AND user_id = 5 AND status = 'closed'
像这样
created_at BETWEEN '2018-01-01T00:00:00+05:30' AND '2019-01-01T00:00:00+05:30'
updated_at BETWEEN '2018-05-01T00:00:00+05:30' AND '2019-05-01T00:00:00+05:30'
user_id = 5
status = 'closed'
这只是一个示例字符串,我想动态分离查询字符串。我知道不能仅仅用
和分割,因为像这样的模式在。。而且
您可能可以使用regex来完成这项工作,但这里有一个解析器可以用于您的用例。它当然可以改进,但应该有效
require 'time'
def parse(sql)
arr = []
split = sql.split(' ')
date_counter = 0
split.each_with_index do |s, i|
date_counter = 2 if s == 'BETWEEN'
time = Time.parse(s.strip) rescue nil
date_counter -= 1 if time
arr << i+1 if date_counter == 1
end
arr.select(&:even?).each do |index|
split.insert(index + 2, 'SPLIT_ME')
end
split = split.join(' ').split('SPLIT_ME').map{|l| l.strip.gsub(/(AND)$/, '')}
split.map do |line|
line[/^AND/] ? line.split('AND') : line
end.flatten.select{|l| !l.empty?}.map(&:strip)
end
需要“时间”
def解析(sql)
arr=[]
split=sql.split(“”)
日期\计数器=0
拆分。每个带有索引do的单位,i|
如果s=='介于'
time=time.parse(s.strip)rescue nil
日期\计数器-=1(如果是时间)
arr这不是一个真正的正则表达式,而是一个简单的解析器
其工作原理是从字符串开始匹配正则表达式,直到它遇到一个空格,后跟和或之间,后跟一个空格字符。结果将从的where\u cause
中删除,并保存在语句中
如果字符串的开头现在以空格开头,后跟between
和空格。它被添加到语句中
,并从中删除,其中\u cause
后面有任何内容,允许1和
。如果到达字符串的结尾或遇到另一个和,则匹配停止
如果第2点不匹配,请检查字符串是否以空格开头,后跟,
和空格。如果是这种情况,请将其从“原因”中删除
最后,将语句
添加到语句
数组(如果它不是空字符串)
所有匹配都不区分大小写
where_cause = "created_at BETWEEN '2018-01-01T00:00:00+05:30' AND '2019-01-01T00:00:00+05:30' AND updated_at BETWEEN '2018-05-01T00:00:00+05:30' AND '2019-05-01T00:00:00+05:30' AND user_id = 5 AND status = 'closed'"
statements = []
until where_cause.empty?
statement = where_cause.slice!(/\A.*?(?=[\s](and|between)[\s]|\z)/mi)
if where_cause.match? /\A[\s]between[\s]/i
between = /\A[\s]between[\s].*?[\s]and[\s].*?(?=[\s]and[\s]|\z)/mi
statement << where_cause.slice!(between)
elsif where_cause.match? /\A[\s]and[\s]/i
where_cause.slice!(/\A[\s]and[\s]/i)
end
statements << statement unless statement.empty?
end
pp statements
# ["created_at BETWEEN '2018-01-01T00:00:00+05:30' AND '2019-01-01T00:00:00+05:30'",
# "updated_at BETWEEN '2018-05-01T00:00:00+05:30' AND '2019-05-01T00:00:00+05:30'",
# "user_id = 5",
# "status = 'closed'"]
将输出:
#=> ["name = 'Tarzan", "Jane'"]
此解决方案还假定SQL查询结构正确。以下查询不会导致您的想法:
where_cause = "created_at = BETWEEN AND"
# TypeError: no implicit conversion of nil into String
# ^ does match /\A[\s]between[\s]/i, but not the #slice! argument
where_cause = "id = BETWEEN 1 AND 2 BETWEEN 1 AND 3"
#=> ["id = BETWEEN 1 AND 2 BETWEEN 1", "3"]
我不确定我是否理解这个问题,特别是考虑到前面的答案,但如果您只是想从字符串中提取指示的子字符串,并且所有列名都以小写字母开头,则可以编写以下内容(其中str
包含问题中给出的字符串):
正则表达式如下:“匹配一个或多个空格,后跟”和“
,后跟一个或多个空格,后跟包含小写字母的正向前瞻”。处于正向前瞻状态时,小写字母不是返回的匹配的一部分 在SQLWHERE子句中可能有许多边缘情况,而您的示例字符串可能无法显示这些情况。你确定这个例子涵盖了所有的边缘情况吗?看起来你想创建一个正则表达式,但不知道从哪里开始。请查看资源,它有很多提示。一旦您准备好了一些表达式,但解决方案仍然存在问题,请使用最新的详细信息编辑问题,我们将很乐意帮助您解决问题。@WiktorStribiż您能正确检查问题吗?这不是重复的,我知道正则表达式的基本知识,它包含和,我不能使用“and”进行拆分,因为在某些情况下,我不需要拆分。因此,您需要帮助的正则表达式在哪里?@TimBiegeleisen我知道这并没有涵盖所有情况,但我已经介绍了一个示例边缘情况,其中对于某些“和”条件,我无法拆分字符串。另外请注意,此解决方案会对字符串进行变异。如果你不想要这个,一定要事先把它复制一下。Datt,我很想知道这是否是你想要的。
where_cause = "created_at = BETWEEN AND"
# TypeError: no implicit conversion of nil into String
# ^ does match /\A[\s]between[\s]/i, but not the #slice! argument
where_cause = "id = BETWEEN 1 AND 2 BETWEEN 1 AND 3"
#=> ["id = BETWEEN 1 AND 2 BETWEEN 1", "3"]
str.split(/ +AND +(?=[a-z])/)
#=> ["created_at BETWEEN '2018-01-01T00:00:00+05:30' AND '2019-01-01T00:00:00+05:30'",
# "updated_at BETWEEN '2018-05-01T00:00:00+05:30' AND '2019-05-01T00:00:00+05:30'",
# "user_id = 5",
# "status = 'closed'"]