我有一个像这样的字符串:
CREATE TABLE foobar (
bar foo,
foo bar
) DISTRIBUTED BY
我想从此字符串中获取所有列定义。我试过:
my_string.scan /CREATE TABLE .*\n([^\n]*?)\n.*DISTRIBUTED BY/
但它不会返回所需的值 ( ["bar foo,", "foo bar"]
)。有任何想法吗?
scan方法的关键是每个新匹配都在最后一个结束时开始:
a = "cruel world"
a.scan(/.../) #=> ["cru", "el ", "wor"]
所以你需要定义你的模式,使它在字符串的开头和中间都匹配。不用说,要建立这样一个后视表达并不容易。
但我想知道这是否足以满足您的特定目标:
s = <<HR
CREATE TABLE foobar (
bar foo,
foo bar
) DISTRIBUTED BY}
HR
ax = s.scan /\s+(.+?)(?:,\n|\n\))/
#=> [["bar foo"], ["foo bar"]]
如您所见,我没有尝试在CREATE TABLE
此处进行匹配,假设字符串已准备好查询。
我认为这就是你想要的:
/CREATE TABLE .*\n((?:.*\n)+).*DISTRIBUTED BY/
(?:.*\n)
匹配单个行,因此((?:.*\n)+)
捕获组 #1 中的一个或多个行。包括最后一行末尾的换行符 ( foo bar
),但您可以在清理逗号的同时删除它(例如 from bar foo,
)。
如果您正在考虑做更复杂的事情,请考虑使用实际的解析器;正则表达式不能很好地与 SQL 配合使用。
大概这就是要走的路。
my_string.split[1..-2].map(&:strip)