次のような文字列があります。
CREATE TABLE foobar (
bar foo,
foo bar
) DISTRIBUTED BY
この文字列からすべての列定義を取得したいと思います。私は試した:
my_string.scan /CREATE TABLE .*\n([^\n]*?)\n.*DISTRIBUTED BY/
しかし、目的の値で返されません ( ["bar foo,", "foo bar"]
) 。何か案は?
スキャン方法の重要なポイントは、最後のマッチが終了したときに新しいマッチが始まることです。
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 の 1 つまたは複数の行をキャプチャします。最後の行末の改行 ( foo bar
) が含まれていますが、コンマをクリーンアップすると同時に削除できます (例えば からbar foo,
)。
もっと複雑なことを考えている場合は、実際のパーサーを使用することを考えてください。正規表現は SQL ではうまく機能しません。
おそらく、これが進むべき道です。
my_string.split[1..-2].map(&:strip)