Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/54.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 在ruby中使用正则表达式拆分数据库查询字符串_Ruby On Rails_Regex_Ruby - Fatal编程技术网

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'"]