如何在两个确定的端点之间多次出现模式

时间:2012-09-17 14:34:41

标签: ruby regex

我有一个字符串:

CREATE TABLE foobar (
   bar foo,
   foo bar
) DISTRIBUTED BY

我想从此字符串中获取所有列定义。我试过了:

my_string.scan /CREATE TABLE .*\n([^\n]*?)\n.*DISTRIBUTED BY/

但它没有返回所需的值(["bar foo,", "foo bar"])。有任何想法吗?

3 个答案:

答案 0 :(得分:3)

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,假设字符串已准备好查询。

答案 1 :(得分:1)

我认为这就是你想要的:

/CREATE TABLE .*\n((?:.*\n)+).*DISTRIBUTED BY/

(?:.*\n)匹配单个行,因此((?:.*\n)+)会捕获组#1中的一行或多行。包含了最后一行(foo bar)末尾的换行符,但您可以在清除逗号的同时删除该换行符(例如来自bar foo,)。

如果您正在考虑做更复杂的事情,请考虑使用实际的解析器;正则表达式与SQL不兼容。

答案 2 :(得分:0)

可能这是要走的路。

my_string.split[1..-2].map(&:strip)