我有一个要分离的查询字符串
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'
这只是一个示例字符串,我想动态分离查询字符串。我知道不能因为AND
BETWEEN .. AND
分手
答案 0 :(得分:1)
您也许可以使用正则表达式来执行此操作,但是这里有一个解析器可能适用于您的用例。当然可以改进,但应该可以。
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
答案 1 :(得分:1)
这不是真正的正则表达式,而是一个简单的解析器。
and
或between
后跟一个空格字符。结果从where_cause
中删除,并保存在statement
中。between
,然后是空格。它被添加到statement
并从where_cause
中删除,之后再加上其他任何内容,允许1个and
。如果到达字符串的末尾或遇到另一个and
,则匹配停止。and
,再后面是空格。如果是这种情况,请从where_cause
中删除它。statement
添加到statements
数组中。所有匹配都不区分大小写。
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'"]
注意: Ruby使用\A
来匹配字符串的开头,使用\z
来匹配字符串的结尾,而不是通常的^
和{ {1}},分别与一行的开头和结尾匹配。参见regexp anchor documentation。
如果愿意,可以将每个$
替换为[\s]
。我添加了它们以使正则表达式更具可读性。
请记住,此解决方案并不完美,但可能会为您提供解决问题的思路。我之所以这样说,是因为它没有考虑列名或字符串上下文中的单词\s
/ and
。
以下原因:
between
将输出:
where_cause = "name = 'Tarzan AND Jane'"
此解决方案还假定结构正确的SQL查询。以下查询不会引起您的想法:
#=> ["name = 'Tarzan", "Jane'"]
答案 2 :(得分:1)
我不确定我是否理解这个问题,特别是鉴于先前的答案,但是如果您只是想从字符串中提取指示的子字符串,并且所有列名都以小写字母开头,则可以编写以下内容(其中LoginWith2fa.cshtml.cs
包含问题中给出的字符串):
str
正则表达式为:“匹配一个或多个空格,后跟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'"]
,后跟一个或多个空格,后跟一个包含小写字母的正向查找”。前瞻性为正,小写字母不属于所返回匹配项的一部分。