根据多个命名的regexp匹配替换string的内容

时间:2017-02-23 10:46:29

标签: ruby regex

我必须重新格式化一堆SQL查询。实际上,像这样的查询会生成语法错误:

insert into table_name (id, name, address) values (4, Pete, My Address Line);

实际上需要

 insert into table_name (id, name, address) values (4, "Pete", "My Address Line");

请注意nameaddress

参数的引号

我在gsub执行此操作时遇到了困难。我写了以下正则表达式:

regexp = /insert into table_name \(id, name, address \) values \(.+?, (?<name>.+?), (?<address>.+?)\);/

现在想要在命名匹配nameaddress的内容周围添加引号。如何在Ruby中执行此操作?

3 个答案:

答案 0 :(得分:1)

这是一种可能性:

sql = "insert into table_name (id, name, address) values (4, Pete, My Address Line);
insert into table_name (id, name, address) values (5, John, My Address Line 2);"

columns_to_replace = %w(name address)

new_sql = sql.gsub(/\((.*?)\) values \((.*?)\)/) do
  columns = Regexp.last_match(1).split(', ')
  values = columns.zip(Regexp.last_match(2).split(', ')).map do |column, value|
    if columns_to_replace.include? column
      format('"%s"', value)
    else
      value
    end
  end
  format('(%s) values (%s)', columns.join(', '), values.join(', '))
end

puts new_sql
# insert into table_name (id, name, address) values (4, "Pete", "My Address Line");
# insert into table_name (id, name, address) values (5, "John", "My Address Line 2");

答案 1 :(得分:0)

r = /
    values\s\(\d+,\s+  # match string
    \K                 # discard match so far
    ([^,]+)            # match all characters other than a comma in capture group 1
    ,\s                # match a comma followed by a space
    ([^)]+)            # match all characters other than a right paren in capture group 2  
    /x                 # free-spacing regex definition mode

sql = "insert into table_name (id, name, address) values (4, Pete, My Address Line);"

puts sql.sub(r, '"\1", "\2"')

打印

insert into table_name (id, name, address) values (4, "Pete", "My Address Line");

请注意,我无法将values\s\(\d+,\s+包裹在正面的后方,因为它是可变长度的。正是出于这个原因,我使用了大大低估的\K指令。

答案 2 :(得分:-1)

wrong_query = "insert into table_name (id, name, address) values (4, Pete, My Address Line);"
right_query = wrong_query.gsub(regexp) do |query|
  name = Regexp.last_match(1)
  address = Regexp.last_match(2)
  [name, address].each do |capture|
    query.sub!(capture, '"' + capture + '"')
  end
  query
end

当名称或地址捕获在整个字符串中不唯一时,这可能会出现严重错误,但对于我的情况,这已经足够了。