Ruby正则表达式在单引号/双引号之间提取字符串,可能包含转义字符

时间:2016-04-05 17:55:26

标签: ruby-on-rails ruby regex

我正在尝试编写一个可以从mysql字符串中提取字符串值的正则表达式。

也就是说,如果我有以下生成的sql字符串,并且我希望能够提取first_name:

my_string = "SELECT * FROM users WHERE first_name = 'first name value'"

我目前所拥有的功能似乎适用于大多数情况:

result = /first_name = ['"](.*?)['"]/i.match my_string

然而,问题是first_name中有'或',即

result = "SELECT * FROM users WHERE first_name = 'first\"s name value'"
or
result = "SELECT * FROM users WHERE first_name = 'first\\'s name value'"

返回的结果只是转义字符的UP值,因此在这些情况下,返回的组将是“first”。如何修复它以便返回整个first_name值?

4 个答案:

答案 0 :(得分:2)

Ruby 1.9+解决方案:名称相同的组

您似乎需要匹配单引号或双引号内的字符串,并且只匹配匹配的引号。

使用Ruby regex功能使用多个具有相同名称的命名组:

/first_name = (?:'(?<val>[^'\\]*(?:\\.[^'\\]*)*)'|"(?<val>[^"\\]*(?:\\.[^"\\]*)*"))/i

请参阅Rubular demo

引号之间的值将在“val”组内。

这是IDEONE Ruby demo

my_string = "SELECT * FROM users WHERE first_name = 'first name value'"
my_string2 = "SELECT * FROM users WHERE first_name = 'first\"s name value'"
my_string3 = "SELECT * FROM users WHERE first_name = 'first\\'s name value'"

rx = /first_name = (?:'(?<val>[^'\\]*(?:\\.[^'\\]*)*)'|"(?<val>[^"\\]*(?:\\.[^"\\]*)*"))/i

puts rx.match my_string  # => first_name = 'first name value'
puts rx.match my_string2 # => first_name = 'first"s name value'
puts rx.match my_string3 # => first_name = 'first\'s name value'

获取“val”(demo):

rx.match(my_string)["val"] # => first name value

Ruby 1.8解决方案

由于自Ruby 1.9以来引入了命名组,并且您需要它在Ruby 1.8中工作,因此请使用受前瞻性解决方案限制的字符类。

/first_name = (['"])((?:(?!\1)[^\\])*(?:\\.(?:(?!\1)[^\\])*)*)\1/i

请参阅Rubular demo

(['"])匹配并捕获到第1组'"(?:(?!\1)[^\\])*匹配除\以外的0 +字符(由于[^\\]),而不是"'(由于(?!\1)) 。 (?:\\.(?:(?!\1)[^\\])*)*)匹配转义序列的0+序列(请参阅\\.),其后跟0 {+ 1}},'"以外的0 +字符。 \反向引用与相应的结束引用匹配。

请参阅another Ruby demo

\1

答案 1 :(得分:0)

我相信这个正则表达式会解决它:

/first_name = ['"]((.*?)['"])*/i

直播示例here

答案 2 :(得分:0)

我在Rubular上测试了它,它似乎得到了你正在寻找的价值。唯一的问题是它还可以捕获你可以替换的逃逸字符:

f_name_match = /first_name = \'(.+)\'/i.match(string).replace('\')

答案 3 :(得分:0)

你可以试试这个

/first_name = ['"](.*?)['"]\z/i

示例here