これが私の文字列です:
SELECT x FROM Table1 WHERE (SELECT y FROM Table2 LIMIT 1) > 15 LIMIT 4
これが私の正規表現です:
SELECT .+ FROM .+ LIMIT (?<LIMITCOUNT>\d{1,4})
2回のキャプチャを実行したい。1つはストリング全体で、もう1つはパランセシスの一部ですが、ストリング全体のみをキャプチャします。私の方法は何ですか?
先読みでキャプチャできます
(?=((?<=^|\s)SELECT .+? LIMIT \d{1,4}(?=\s|$)|(?<=\()SELECT .+? LIMIT \d{1,4}(?=\))))
これにより、例で2つのクエリがキャプチャされます!グループ1を使用してアクセスします
ここで試してみてください
ここで何が得られているかわかります。複数の一致を取得するために呼び出す場合Matches
、他の一致の「範囲内」の一致は検索されません。最初の一致を見つけて、その一致の終了後に再度検索を開始します。
すぐに使える方法でやりたいことがあるとは思わないので、手動で行う必要があります。いくつかの変更を加える必要があります。
.+
の貪欲でない(.+?
)を作成して、2番目ではなくFROM
最初のに一致するようにしFROM
ます。現時点では2番目FROM
と一致しており、これによりステップ2が台無しになります。.+
2番目の周りに別のキャプチャグループを追加します(?<PotentialNested>.+)
。貪欲に保ち、最初ではなくLIMIT
2番目に一致するようにします。LIMIT
PotentialNested
キャプチャをさらに一致するかどうかを再帰的にチェックし続けるメソッドを記述します。public static IEnumerable<Match> NestedMatches(this Regex regex, string input)
{
var potentialNested = new Queue<string>();
foreach (Match m in regex.Matches(input))
{
yield return m;
potentialNested.Enqueue(m.Groups["PotentialNested"].Value);
}
while (potentialNested.Count > 0)
{
foreach (Match m in regex.Matches(potentialNested.Dequeue()))
{
yield return m;
potentialNested.Enqueue(m.Groups["PotentialNested"].Value);
}
}
}
編集:実際には、このすべての後、2つのネストされた用語が隣り合っている場合は、それでも機能しません。
SELECT x FROM Table1 WHERE
((SELECT y FROM Table2 LIMIT 1) + (SELECT y FROM Table2 LIMIT 1)) > 15
LIMIT 4
これが潜在的な入力である場合は、PotentialNested
キャプチャグループがブラケットのバランスをとっていることを確認してみてください。
(?<PotentialNested>((?<BR>\()|(?<-BR>\))|[^()]*)+)