2

私はそれを短く簡潔に保つようにしています。SQL 形式でクエリを受け取り、XML を検索するプログラムを作成する必要があります。現在、文字列を論理的な断片に分解して、それらを操作できるようにしようとしています。入力として文字列があり、MatchCollection を出力として取得したいと考えています。

以下のテスト文字列は、単純にするためにユーザーに課す特別な形式であることに注意してください。1 行に 1 つのステートメントのみが許可され、ネストされたクエリは除外されます。

string testString = "りんごを選択 \n dblp から \r 食べた場所 \n すべてをグループ化 \r HAVING NO SHAME \n";

次のパターンで正規表現を使用します。

Regex reg = new Regex(@"(?<select> \A\bselect\b .)" +  
                      @"(?<from> ^\bfrom\b .)" +
                      @"(?<where> ^\bwhere\b .)" +
                      @"(?<groupBy> ^\bgroup by\b .)" +
                      @"(?<having> ^\bhaving\b .)"
                      , RegexOptions.IgnoreCase | RegexOptions.Multiline
                      );

私の知る限り、これにより、テスト文字列を持つすべてのグループに一致するはずです。各行の先頭にある「select」とそれに続く改行以外の文字が完全に一致するものを探します。

次に、コレクションを作成します。

MatchCollection matches = reg.Matches(testString);

それが機能することを確認するために、 foreach を使用し、次のように一致を出力しました。

foreach(Match match in matches)
{
    Console.WriteLine("Select: {0}", match.Groups["select"]);
   //and so on
}

問題は、コレクションが常に空であることです。正規表現のどこかに欠陥があるに違いありませんが、経験が浅すぎて見つけることができません。助けていただけませんか?どうもありがとうございました!


の代わりに .* を使用してみました。そう言われるまで。複数の文字を計算することさえできます。これが問題になる可能性があることは間違いありませんが、交換しても結果が得られません。

正規表現が改行を見つけるまで、定義された単語で始まり、それに追加された文字を含む行を照合するのが非常に難しい理由がわかりません。これは比較的簡単な作業だと思います。

4

4 に答える 4

3

他の人が提案したように、行末記号を明示的に一致させるだけでなく、スペースをより適切に処理する必要があると思います。ユーザーが \r と \n のどちらかを選択できると仮定して、試してください

@"(?<select>\Aselect .+)[\n\r]" +
@"(?<from>\s*from .+)[\n\r]" +
@"(?<where>\s*where .+)[\n\r]" +
@"(?<groupBy>\s*group by .+)[\n\r]" +
@"(?<having>\s*having .+)[\n\r]"

正規表現を使用している限り、おそらくもう少しうまくやりたいと思うでしょう:

@"\Aselect (?<select>.+)[\n\r]" +
@"\s*from (?<from>.+)[\n\r]" +
@"\s*where (?<where>.+)[\n\r]" +
@"\s*group by (?<groupBy>.+)[\n\r]" +
@"\s*having (?<having>.+)[\n\r]"

この種の使用に対する正規表現の最大の問題は、エラー メッセージが失敗したということだけだということです。ユーザーが何を間違えたかについて、それ以上の情報をユーザーに提供することはできません。

于 2008-11-15T21:55:23.443 に答える
0

動作する正規表現を作成しようとはしていませんが、いくつかの問題が見られます。他の人は最初の 2 つの問題を指摘しましたが、3 つ目の問題は指摘しませんでした。

  1. 「りんご」などの可変部分に一致する単一のドットを使用することはできません。\w+ または \S+ を試してください
  2. 文字列に改行が埋め込まれています。[\r\n]+ または \s+ でそれらを一致させる必要があります
  3. .NET 正規表現エンジンは \n を改行として扱いますが、\r または \r\n は扱いません。したがって、^ は \n の後では一致しますが、\r の後では一致しません。手順 2 を実行する場合は、いずれにせよアンカーは必要ないため、アンカーを削除します。
于 2008-11-16T10:02:21.760 に答える
0

改行の一致に問題がある可能性があります: LF (Unix 標準)、CR (MacOS)、または CR LF (Windows) ですか? わからない場合は、おそらく次のように一致させる必要があります。[\n\r]+

edit : テスト文字列に改行を囲む空白を含めましたが、これは rexex では考慮されていません。

(?<from>^\s*from\b.*[\n\r]+$)
于 2008-11-16T00:00:29.620 に答える
0

あなたが言ったように、キーワードを一致させてから (.+) を使用して残りの行を一致させるのは簡単です。しかし、介在するすべての文字を一致させる必要があり、それを行っていません。(^ 行アンカーは、区切り自体ではなく、行区切りの後の位置と一致します。) \s+ を使用して、行区切りと次の行の先頭の空白を消費できます。

@"select\s+(?<select>.+)\s+" +
@"from\s+(?<from>.+)\s+" +
@"where\s+(?<where>.+)\s+" +
@"group by\s+(?<groupBy>.+)\s+" +
@"having\s+(?<having>.+)";

また、SQL キーワードが取り込まれないように再配置しました。名前付きグループを使用しているため、冗長に思えます。

于 2008-11-16T02:57:59.697 に答える