1

次のようなログファイルがあります。

2012-05-04 01:10:35;301383027;00133608663205759673480010256592;103;エラー;AbstractTreatment:119;blah1

何とか2

何とか3

2012-05-02 01:00:22;301382163;00133591322220336011720010256592;103;エラー;AbstractTreatment:119;blah4

何とか5

何とか6

2012-05-02 01:00:23;301382163;00133591322220336011720010256592;103;エラー;AbstractTreatment:119;blah7

何とか8

何とか9

日付、重大度、メッセージの 3 つのグループをそれぞれキャプチャした 3 つの一致が必要です。

このパターンを使ってみました

(20[0-9]{2}-[0-2][0-9]-[0-9]{2} [0-2][0-9]:[0-5][0-9]:[0-5][0-9]);[^;]*;[^;]*;[^;]*;([^;]*);(.*)

単一行オプションを有効にすると、1 つの一致 (入力全体) があり、このオプションを無効にすると、メッセージは完全にはキャプチャされません (日付と同じ行の部分のみ)。

正しく取得したい 3 つの値を持つログ エントリと同じ数の一致を取得するにはどうすればよいですか?

編集:次のような一致をキャプチャしようとしています:

日付: 2012-05-04 01:10:35

重大度:エラー

メッセージ: AbstractTreatment:119;blah1

何とか2

何とか3

4

2 に答える 2

5

ここで2つのトリックがあります。

  1. 「。」"\n" を含まず、 RegexOptions.Multiline を設定する必要はありません。

  2. 別の日付/時刻パターンまたは終了文字 ($) を区切り文字として使用する必要がありますが、これらは一致に含めることはできません。(それ以外の場合は、次の一致を検索する前に入力から区切り文字を除外する必要があります)。これには、「 Zero-Width Positive Lookahead Assertions
    」と呼ばれる特別なグループ化式を (?= subexpression) の構文で使用する必要があります。

ログをテストするために、「ログ」設定変数に保存しました。

string log = Settings.Default.Log;
string datePattern = @"20[0-9]{2}-[0-2][0-9]-[0-9]{2} [0-2][0-9]:[0-5][0-9]:[0-5][0-9]";
string pattern = @"(?<date>" + datePattern + @");[^;]*;[^;]*;[^;]*;(?<severity>[^;]*);(?<message>(.|\n)*?)(?=(" + datePattern + @"|$))";
Match mtc = Regex.Match(log, pattern);

while (mtc.Success)
{
    Console.WriteLine("Date: " + mtc.Groups["date"].Value);
    Console.WriteLine("Severity: " + mtc.Groups["severity"].Value);
    Console.WriteLine("Message: " + mtc.Groups["message"].Value);

    mtc = mtc.NextMatch();
}

出力は次のようになります。

Date: 2012-05-04 01:10:35
Severity: ERROR
Message: AbstractTreatment:119;blah1

blah2

blah3


Date: 2012-05-02 01:00:22
Severity: ERROR
Message: AbstractTreatment:119;blah4

blah5

blah6


Date: 2012-05-02 01:00:23
Severity: ERROR
Message: AbstractTreatment:119;blah7

blah8

blah9
于 2012-05-12T01:26:11.293 に答える
2
  Regex r = new Regex(
      @"^(?<date>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2});[^;]*;[^;]*;[^;]*;(?<severity>[^;]*);(?<message>.*(\n+(?!\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2};)[^\n]+)*)",
      RegexOptions.Multiline | RegexOptions.ExplicitCapture);

アイデアは、.*が最初の行の残りを消費した後、 \n+1 つ以上の行セパレーターを[^\n]+消費し、次の空でない行の内容を消費するという(?!\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2};)ものです。ライン。(もちろん、日付で始まる行は、次のログ エントリの開始と見なされるためです。)

このMultilineオプションにより、^アンカーは文字列の先頭だけでなく、改行の後でも一致します。 ExplicitCapture名前付きグループのみがキャプチャされることを意味する(?:...)ため、単純なグループがキャプチャされないようにするために使用する必要はありません。ExplicitCapture名前付きグループを使用するときはいつでも使用することをお勧めします。名前付きおよび番号付きのグループは、.NET 正規表現で奇妙な相互作用をします。

于 2012-05-12T03:50:49.873 に答える