1

TL; DR

C#正規表現を使用してレポートを解析し、MultiLineを有効にして、名前付きグループを持つ単一の(複雑な)正規表現パターンを使用してファイル全体を処理しています。(およびCaptureCollection。)

レポートのセクションが順序どおりに表示されないか、予測できない方法で欠落しています。

それらが表示される順序に関係なく、どのようにそれらを一致させるのですか?

序文

System.Text.RegularExpressionsを使用してC#(.Net 3.5)の正規表現を使用してレポートを解析しています。レポートの1つのセクションは次のようになります。

     Section Z              0 __ base 10
                            2 __ 19/04 20:06:39
                            2 __ 19/04 20:15:49
                          1.8 __ 19/04 20:09:35
                          1.6 __ 19/04 20:07:01
                          1.6 __ 19/04 20:08:29
     Section 7            0.8 __ base 10
                            8 __ 18/04 21:03:01
                          7.3 __ 18/04 21:02:17
                          3.7 __ 19/04 08:41:09
                          3.4 __ 19/04 00:13:08
                          3.3 __ 18/04 21:02:50
     Section C              0 __ base 10
                         19.7 __ 19/04 10:25:06
                         11.1 __ 19/04 10:15:01
                          8.8 __ 19/04 10:14:50
                          7.2 __ 19/04 19:51:37
                          6.1 __ 19/04 14:19:47

(?mx)私の正規表現は、オプション(MultiLine、IgnorePatternWhitespace)を使用して、テキストファイル全体と一致します。統計セクションにはそれぞれのサブ統計があるため、各セクションの(オプションの?)非キャプチャグループ((?:match_this_text))を手動で作成し、次のように、発生していると思った順序でパターンに配置しました。

(?mx) #Turn on options multiline, ignore whitespace.
(?: # base 10 statistic sections
    (?:
        [\s-[\n\r]]*(?i:Section\sZ)\s+(?<base10_SectionZ>\d+\.\d|\d+)\s__\sbase\s10
        (?:\r?\n)+
        (?:\s+(?<base10_SectionZ_instance>\d+\.\d|\d+)\s__\s(?<base10_SectionZ_instance_time>\d\d/\d\d\s\d\d:\d\d:\d\d)(?:\r?\n)+)+
    )?
    (?:
        [\s-[\n\r]]*(?i:Section\s7)\s+(?<base10_Section7>\d+\.\d|\d+)\s__\sbase\s10
        (?:\r?\n)+
        (?:\s+(?<base10_Section7_instance>\d+\.\d|\d+)\s__\s(?<base10_Section7_instance_time>\d\d/\d\d\s\d\d:\d\d:\d\d)(?:\r?\n)+)+
    )?
    (?:
        [\s-[\n\r]]*(?i:Section\sC)\s+(?<base10_SectionC>\d+\.\d|\d+)\s__\sbase\s10
        (?:\r?\n)+
        (?:\s+(?<base10_SectionC_instance>\d+\.\d|\d+)\s__\s(?<base10_SectionC_instance_time>\d\d/\d\d\s\d\d:\d\d:\d\d)(?:\r?\n)+)+
    )?
)

各セクションの非キャプチャグループの最初の行は「セクションヘッダー」と一致し、2番目の行はヘッダーと統計インスタンスの間の改行と一致し、3番目の行は個々の統計インスタンス(繰り返し、n個のインスタンス)と一致します。

問題

このレポートを生成するプログラムは、実行中のバージョンに応じて、各セクション(たとえば、セクションZ、セクション7、セクションC)を異なる順序で出力し、特定の状況では特定のセクションが欠落しています。2番目のテストファイルに対して実行したところ、セクションの順序が狂っていたために失敗しました。

したがって、セクションCはセクションZの前に発生する可能性がありますが、正規表現パターンでは、ZがCの前に発生することを想定しています。

基本的に、セクションが表示される順序に関係なく、同じ正規表現を(上記の名前付きグループを使用して)一致させて抽出し、上記のテストデータとこのテストデータの両方に一致させるようにします。

     Section 7            0.8 __ base 10
                            8 __ 18/04 21:03:01
                          7.3 __ 18/04 21:02:17
                          3.7 __ 19/04 08:41:09
                          3.4 __ 19/04 00:13:08
                          3.3 __ 18/04 21:02:50
     Section C              0 __ base 10
                         19.7 __ 19/04 10:25:06
                         11.1 __ 19/04 10:15:01
                          8.8 __ 19/04 10:14:50
                          7.2 __ 19/04 19:51:37
                          6.1 __ 19/04 14:19:47
     Section Z              0 __ base 10
                            2 __ 19/04 20:06:39
                            2 __ 19/04 20:15:49
                          1.8 __ 19/04 20:09:35
                          1.6 __ 19/04 20:07:01
                          1.6 __ 19/04 20:08:29
4

4 に答える 4

1

各セクションをキャプチャしたいだけですか?

これはうまくいきませんか?(Section ..*(?:\r.*){0,5})

http://regexr.com?30nfd

于 2012-04-21T01:55:29.110 に答える
0

この場合、1つの巨大な正規表現よりも2つの異なる正規表現を使用する方がよいと思います。File.RealAllLines次に、各行を。でループし ますIf String.Contains("Section")。セクションが含まれている場合は、新しいセクションオブジェクトを作成し、セクション正規表現を実行して新しいセクションオブジェクト(セクション名とセクションデータ)を設定します。セクションが含まれていない場合は、追加のセクションデータに対して別の正規表現を実行し、それを現在のセクションオブジェクトに追加します。

于 2012-04-20T23:37:17.697 に答える
0

正規表現エンジンに何も一致しないオプションを与えるべきではありません。
オプションの何かを見つける前に、多くの「何もない」を見つけて歩き回ります。

編集

ブロックマッチ(任意の順序で、シーケンシャル) だけが必要な場合は、このようなものが機能します。
変更を加えて、あなたのやり方で:

(?:
   (?: Section ...  (?<sec_7> 7)
   )
 | (?: Section ...  (?<sec_C> C)
   )?
 | (?: Section ...  (?<sec_Z> Z)
   )
)
(?: Section ...  (?!\k<sec_7>) (?<sec_7>  7) )?
(?: Section ...  (?!\k<sec_C>) (?<sec_C>  C) )?
(?: Section ...  (?!\k<sec_Z>) (?<sec_Z>  Z) )?

因数分解できる場合は、次のようになります。

(?: Section ...  (?<sec_a>(?:7|C|Z) )
(?: Section ...  (?<sec_b>(?!\k<sec_a>)(?:7|C|Z)  )?
(?: Section ...  (?<sec_c>(?!\k<sec_a>|\k<sec_b>)(?:7|C|Z)  )?
#
# Then after match check <sec_a/b/c> for its value

ブロックの一致を気にしない場合:
ケースは OR 条件のみを中心に展開します。したがって、次のように簡単にできます。

# base 10 statistic sections
    (?: ..)
  |
    (?: ..)
  |
    (?: ..)

「base 10」セクションの一致の各一致は、while ループで次のようにチェックする必要があります。

Match m = Regex.Match(input, regex, RegexOptions.IgnorePatternWhitespace);
while (m.Success)
{
   if (m.Groups["base10_Section7"].Success)  {    }
   else
   if (m.Groups["base10_SectionZ"].Success)  {    }
   else
   if (m.Groups["base10_SectionC"].Success)  {    }
   m = m.NextMatch();
}

これでも軽減できます。たとえば、7、Z、C を 1 つのチャンクに組み合わせることができます。
これにより、OR (|) が残り、たとえば「ベース 2」
やその他の形式など、他の個別の項目が一致します。1 つのフォームが一致します。とにかく要チェックです。

string input = @"
    Section Z              0 __ base 10
                           2 __ 19/04 20:06:39
                           2 __ 19/04 20:15:49
                         1.8 __ 19/04 20:09:35
                         1.6 __ 19/04 20:07:01
                         1.6 __ 19/04 20:08:29
    Section P           16.1 __ base 2
    Section 7            0.8 __ base 10
                           8 __ 18/04 21:03:01
                         7.3 __ 18/04 21:02:17
                         3.7 __ 19/04 08:41:09
                         3.4 __ 19/04 00:13:08
                         3.3 __ 18/04 21:02:50
    Section C              0 __ base 10
                        19.7 __ 19/04 10:25:06
                        11.1 __ 19/04 10:15:01
                         8.8 __ 19/04 10:14:50
                         7.2 __ 19/04 19:51:37
                         6.1 __ 19/04 14:19:47
    Section r           49.2 __ Base 2
";

string regex = @"
   # base 10 statistic sections
       (?:
         [\s-[\n\r]]*(?i:Section\s(?<base10_Section>Z|7|C)\s+(?<Base10>\d+\.\d|\d+)\s__\sbase)\s10
         (?:\r?\n)+
         (?:\s+(?<Instance>\d+\.\d|\d+)\s__\s(?<Time>\d\d/\d\d\s\d\d:\d\d:\d\d)(?:\r?\n)+)+
       )
     |  # Or, base 2 statistic sections
       (?:
         [\s-[\n\r]]*(?i:Section\s(?<base2_Section>R|P)\s+(?<Base2>\d+\.\d|\d+)\s__\sbase)\s2
         (?:\r?\n)+
       )
   # |  Or, something else

";

Match m = Regex.Match(input, regex, RegexOptions.IgnorePatternWhitespace);
int matchCount = 0;
while (m.Success)
{
    Console.WriteLine("\nMatch " + (++matchCount) + "\n------------------");
    // Check base 10
    if (m.Groups["base10_Section"].Success)
    {
        Console.WriteLine("Section (base10)  '" + m.Groups["base10_Section"] + "'  =  '" + m.Groups["Base10"] + "'\n");

        int count = m.Groups["Instance"].Captures.Count;
        // Instance
        for (int j = 0; j < count; j++)
            System.Console.WriteLine("    Instance (" + j + ") =  '" + m.Groups["Instance"].Captures[j] + "' ");
        // Time
        for (int j = 0; j < count; j++)
            System.Console.WriteLine("    Time(" + j + ") =  '" + m.Groups["Time"].Captures[j] + "' ");
        // Combined ..
        for (int j = 0; j < count; j++)
            System.Console.WriteLine("    Instance,Time  (" + j + ") =  '" +
                                          m.Groups["Instance"].Captures[j] + "' __ '" +
                                          m.Groups["Time"].Captures[j] + "' ");
    }
    else
    // Check base 2
    if (m.Groups["base2_Section"].Success)
        Console.WriteLine("Section (base2)  '" + m.Groups["base2_Section"] + "'  =  '" + m.Groups["Base2"] + "'\n");

    m = m.NextMatch();
}
于 2012-04-21T19:40:02.357 に答える
0

\G オプションを使用して、各式を前の結果に固定することをお勧めします。これにより、セクション間に不要なものがないことが保証されます。

また、セクションに対してより一般的な式を使用できます。

(?mx) #Turn on options multiline, ignore whitespace.
\G
(?: # base 10 statistic sections
    (?:
        [\s-[\n\r]]*(?i:Section\s(Z|7|C))\s+(?<base10_Section>\d+\.\d|\d+)\s__\sbase\s10
        (?:\r?\n)+
        (?:\s+(?<base10_Section_instance>\d+\.\d|\d+)\s__\s(?<base10_Section_instance_time>\d\d/\d\d\s\d\d:\d\d:\d\d)(?:\r?\n)+)+
    )
)

その後、セクションが重複または欠落していないことを確認します。実際に見てください

于 2012-04-21T10:29:54.263 に答える