2

現在、内部ログ ファイル (log4php、log4net、および log4j によって生成される) のパーサーに取り組んでいます。これまでのところ、ログを解析するための適切な正規表現がありますが、厄介な点が 1 つあります。一部のログ メッセージは複数の行にまたがっており、適切に一致させることができません。私が今持っている正規表現はこれです:

(?<date>\d{2}/\d{2}/\d{2})\s(?<time>\d{2}):\d{2}:\d{2}),\d{3})\s(?<message>.+)

ログ形式 (パーサーのテストに使用) は次のとおりです。

07/23/08 14:17:31,321 log 
message
spanning
multiple
lines
07/23/08 14:17:31,321 log message on one line

今パーサーを実行すると、ログが始まる行だけが得られます。複数行にまたがるように変更すると、1 つの結果 (ログ ファイル全体) しか得られません。


@サムジャドソン:

RegexOptions.Singleline フラグを正規表現に渡す必要があるため、「.」改行を除くすべての文字 (デフォルト) だけでなく、すべての文字に一致します。

私はそれを試しましたが、ファイル全体に一致します。また、メッセージグループを .+? に設定しようとしました。(貪欲ではない)が、それは単一の文字に一致します(これは私が探しているものでもありません)。

問題は、メッセージのパターンが日付グループにも一致することです。そのため、改行で改行されない場合、メッセージは延々と続くだけです。


現在、メッセージ グループにこの正規表現を使用しています。ログメッセージの開始と同じパターンがログメッセージにない限り、機能します。

(?<message>(.(?!\d{2}/\d{2}/\d{2}\s\d{2}:\d{2}:\d{2},\d{3}\s\[\d{4}\]))+)
4

5 に答える 5

3

これは、ログ メッセージの行頭に日付が含まれていない場合にのみ機能しますが、「メッセージ」グループの日付に否定先読みアサーションを追加してみてください。

(?<date>\d{2}/\d{2}/\d{2})\s(?<time>\d{2}:\d{2}:\d{2},\d{3})\s(?<message>(.(?!^\d{2}/\d{2}/
\d{2}))+)

これには RegexOptions.MultiLine フラグを使用する必要があることに注意してください。

于 2008-09-03T10:37:36.340 に答える
2

「メッセージ行」を「ログ行」と区別できることが明らかに必要です。メッセージ部分が新しい行の後に日付/時刻で始まることを許可すると、メッセージの一部とそうでないものを判断する方法がまったくありません。したがって、ドットを使用する代わりに、日付と時刻が続く改行を含まないものを許可する式が必要です。

ただし、個人的には、正規表現を使用してログ エントリ全体を解析するつもりはありません。私は独自のループを使用して各行を繰り返し処理し、1 つの単純な正規表現を使用して行が新しいエントリの開始かどうかを判断することを好みます。また、読みやすさの点からも、これが私の好みです。

于 2008-09-03T10:37:02.630 に答える
1

あなたが抱えている問題は、正規表現パターンを終了して、1 つのメッセージがいつ終了し、次に開始するかを認識できるようにする必要があることです。

デフォルトモードで実行していたとき、改行は暗黙のターミネータとして機能していました。

問題は、複数行モードに入るとターミネータがないため、パターンがファイル全体を飲み込んでしまうことです。非貪欲は、可能な限り少数の文字に一致しますが、そのうちの 1 つだけになります。

ここで、次のメッセージの日付をターミネータとして使用すると、パーサーは 1 行おきにしか取得できないと思います。

パターンを終了するためにファイルに何か他のものがありますか?

于 2008-09-03T10:34:08.063 に答える
0

適切なパーサー ジェネレーターを使用してファイルを解析する方がはるかに簡単であることに気付くかもしれません - ANTLR は C# で生成できます... コンテキスト フリー パーサーは、「取得」するまでは難しいように見えますが、その後は、はるかにシンプルで使いやすくなっています。正規表現より...

于 2008-09-03T12:26:07.703 に答える
0

を渡す必要がありRegexOptionsます。シングルライン フラグを正規表現に追加すると、「.」改行を除くすべての文字 (デフォルト) だけでなく、すべての文字に一致します。

于 2008-09-03T10:19:00.923 に答える