none
正規表現マッチングで処理が帰ってこない RRS feed

  • 質問

  • いつもお世話になっております。下記のコードを実行すると、Match()から処理が帰ってきません。数分すると帰ってきますが、もっと長い文字列になると数時間帰ってきません。これはどうしようもないでしょうか。宜しくお願い致します。

    環境:WinXP VS2005 C#


       string sz1, sz2;
       Match match;
       Regex regex;

       sz1 = "(.*-?[0-9]+.?[0-9]*) (.*-?[0-9]+.?[0-9]*) (.*-?[0-9]+.?[0-9]*) (.*-?[0-9]+.?[0-9]*) (.*-?[0-9]+.?[0-9]*) (.*-?[0-9]+.?[0-9]*) (.*-?[0-9]+.?[0-9]*) (.*-?[0-9]+.?[0-9]*) (.*-?[0-9]+.?[0-9]*) (.*-?[0-9]+.?[0-9]*)";
       sz2 = "55.55  55.55  55.55  55.55  55.55  55.55  55.55  55.55  55.55  55.55";
       regex = new Regex( sz1 );
       match = regex.Match( sz2 );

     

    2006年11月8日 11:03

回答

  • 取り敢えずなのですが、この "(.*-?[0-9]+.?[0-9]*)" の1つ1つは "55.55" に対応することを意図しているのでしょうか?

    試しに、sz1 = "(.*-?[0-9]+.?[0-9]*)" と sz2 に対して regex.Match(sz2); をかけてみると、結果の match は sz2 全体になってしまいます。

    ".*" の記述が最大限に働いて、".*" が最後の1つ前の 55.55 まで全部一致してしまった結果だと思います。ですので「ありそうなパターンが多すぎる」ことで Regex に時間がかかり過ぎているのではないかと推測されます。

    区切り記号としてスペースを仮定されているのでしたら、次のように sz1 を書き換えられるのは如何でしょうか?

    sz1 ="\\s*(-?[0-9]+\\.?[0-9]*)\\s+(-?[0-9]+\\.?[0-9]*)\\s+(-?[0-9]+\\.?[0-9]*)\\s+(-?[0-9]+\\.?[0-9]*)\\s+(-?[0-9]+\\.?[0-9]*)\\s+(-?[0-9]+\\.?[0-9]*)\\s+(-?[0-9]+\\.?[0-9]*)\\s+(-?[0-9]+\\.?[0-9]*)\\s+(-?[0-9]+\\.?[0-9]*)\\s+(-?[0-9]+\\.?[0-9]*)";

    あと、sz1 には "\\s*(-?[0-9]+\\.?[0-9]*)" を記述して、

    regex = new Regex(sz1);
    match = regex.Match(sz2);
    while (match.Success)
    {
    Group g = match.Groups[0];
    CaptureCollection cc = g.Captures;
    for (int j = 0; j < cc.Count; j++)
    {
    Capture c = cc[j];
    System.Console.WriteLine("Capture" + j + "='" + c + "', Position=" + c.Index);
    }
    System.Console.WriteLine(match.Index);
    match = match.NextMatch();
    }

    のように NextMatch をとっていく方法もあると思います。

     

    2006年11月8日 12:17
  • Regex それ自身に timeout は見付からないようですので、Thread を作成して一定期間待つというのは如何でしょうか?

    Join が Timeout した場合には、Abort を送って Thread を強制的に止めてしまうわけです。

     

    2006年11月10日 7:14

すべての返信

  • 取り敢えずなのですが、この "(.*-?[0-9]+.?[0-9]*)" の1つ1つは "55.55" に対応することを意図しているのでしょうか?

    試しに、sz1 = "(.*-?[0-9]+.?[0-9]*)" と sz2 に対して regex.Match(sz2); をかけてみると、結果の match は sz2 全体になってしまいます。

    ".*" の記述が最大限に働いて、".*" が最後の1つ前の 55.55 まで全部一致してしまった結果だと思います。ですので「ありそうなパターンが多すぎる」ことで Regex に時間がかかり過ぎているのではないかと推測されます。

    区切り記号としてスペースを仮定されているのでしたら、次のように sz1 を書き換えられるのは如何でしょうか?

    sz1 ="\\s*(-?[0-9]+\\.?[0-9]*)\\s+(-?[0-9]+\\.?[0-9]*)\\s+(-?[0-9]+\\.?[0-9]*)\\s+(-?[0-9]+\\.?[0-9]*)\\s+(-?[0-9]+\\.?[0-9]*)\\s+(-?[0-9]+\\.?[0-9]*)\\s+(-?[0-9]+\\.?[0-9]*)\\s+(-?[0-9]+\\.?[0-9]*)\\s+(-?[0-9]+\\.?[0-9]*)\\s+(-?[0-9]+\\.?[0-9]*)";

    あと、sz1 には "\\s*(-?[0-9]+\\.?[0-9]*)" を記述して、

    regex = new Regex(sz1);
    match = regex.Match(sz2);
    while (match.Success)
    {
    Group g = match.Groups[0];
    CaptureCollection cc = g.Captures;
    for (int j = 0; j < cc.Count; j++)
    {
    Capture c = cc[j];
    System.Console.WriteLine("Capture" + j + "='" + c + "', Position=" + c.Index);
    }
    System.Console.WriteLine(match.Index);
    match = match.NextMatch();
    }

    のように NextMatch をとっていく方法もあると思います。

     

    2006年11月8日 12:17
  •  Takashi SAKAMOTO様、いつもありがとうございます。

    確かに項目が増えるごとにパターンは無限に増えていきますね。時間がかかることも納得できました。正規表現、マッチング処理等、提示して下さったサンプルを元に、もう一度見直してみたいと思います。ありがとうございました。

    2006年11月9日 1:25
  • お世話になります。

    Match()で時間がかかる問題なのですが、タイムアウトを設けて処理を抜けることは不可能でしょうか。そのような機能を探しているのですが見つかりません。時間がかかるかどうかは実行してみないとわからないし、途中でキャンセルも不可でしょうか。宜しくお願い致します。

    2006年11月10日 6:49
  • Regex それ自身に timeout は見付からないようですので、Thread を作成して一定期間待つというのは如何でしょうか?

    Join が Timeout した場合には、Abort を送って Thread を強制的に止めてしまうわけです。

     

    2006年11月10日 7:14
  • ありがとうございました。ご提示いただいた方法で目的の動作が実現できました。感謝いたします。

    2006年11月10日 9:56