1
        Regex regexObj = new Regex(
        @"([A-Za-z_][A-Za-z_0-9]*)(:)(([-+*%])?(\d*\.?\d*)?)*"
           , RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace);

        var subjectString = "a:123+456;b:456;";
        Match matchResults = regexObj.Match(subjectString);
        while (matchResults.Success) {
            for (int i = 1; i < matchResults.Groups.Count; i++) {
                Group grp = matchResults.Groups[i];
                if (grp.Success) {
                    Console.WriteLine("st:" + grp.Index + ", len:" + grp.Length + ", val:" + grp.Value);
                }
            }
            matchResults = matchResults.NextMatch();
        }

出力:

st:0、len:2、val:.a

st:2、len:1、val ::

st:6、len:0、val:

st:6、len:0、val:

4

1 に答える 1

2

「」をの有効な履行と見なすことができるため\d*、番号が発生する前にキャプチャが完了します。

グループのキャプチャを開始するには、オプション(*)ではなく必須(+)として少なくとも1桁を指定する必要があります。

明確にするために、正規表現がエラーなしでコンパイルされたが、特定のグループの何もキャプチャしない場合、それは一致が成功しなかったことを意味しません。

これは、何かをキャプチャしたにもかかわらず、試合が成功したことを意味します。つまり、設計上、そのグループを通過させることになります。

たとえば、あなた自身の正規表現のこの部分では、次の(([-+*%])?(\d*\.?\d*)?)*ように言っています。オプションの記号の後に10進数が続くことを期待していますが、それもオプションです。何も見つからなかった場合は問題ありませんが、RegExpエンジンの皆さん、これが発生したかどうかは関係ありませんので、気にしないでください。

これをさらに分解してみましょう:

  • \d*\.\d*ドットが間にある任意の桁数(まったくないものを含む)を持つものを意味します。したがって、、、、0.はすべて有効な一致であり.、 。.123も同様2.1です。
  • これをオプションにすることで、ドットも必要ないので、(\d*\.\d*)?一致する""(空の文字列)と言っています。
  • 上記の文字列が一致する前に何かが発生した場合は、示された4つの記号のいずれかである必要がある([-+*%])?(\d*\.?\d*)?と書いてください。しかし、あなたはそれが起こらなければならないことを必要としません(ので)。また、上記のグループは空の文字列と一致する可能性があるため、エンジンが文字列を有用なものと一致させることに成功しなかった場合、示された4つの記号のいずれかが存在するということは、このグループが引き続き成功することを意味します。数も含めて全体。?
  • さて、前の定義をとしてグループ化する(([-+*%])?(\d*\.?\d*)?)*ことで、それもオプションにし、基本的に正規表現エンジンに、この定義の最初の部分より先に答えを探しなくても大丈夫だと伝えます。

それで、あなたはどのように進めるべきですか?いつグループをオプションにする必要がありますか?エンジンがこのグループに一致しなかった場合でも、ステートメントは引き続き有効であり、この値を気にしないことを知って、グループをオプションにする必要があります。

また、補足として、ほぼすべてをキャプチャするべきではありません。(start,length)エンジンはメモリ内で要求するグループのペアを保持し、パフォーマンスが低下するため、自分にとって重要な値のみをキャプチャします。通常のグループ化の代わりに()非キャプチャーグループインジケーター(?:)を使用します。これにより、メモリを保持しながら、グループ化とより高いレベルの制御が可能になります。

グループをキャプチャするもう1つの用途は、正規表現で一致するコンテンツを参照する場合です。

<(\w+)>.*?</\1>

これは、一致する終了タグを持つXMLタグをキャプチャします。また、上記の例はデモンストレーションのみを目的としており、一般的に言えば、正規表現を使用してあらゆる種類の階層ドキュメントを解析することは、大文字のB、大文字のI、悪いアイデアです。

于 2012-10-20T07:03:00.930 に答える