2008-09-03 11 views
2

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

(?<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つだけ(ログファイル全体)になります。


@samjudson: "" あなたは、正規表現の中でRegexOptions.Singlelineフラグを渡すようにする必要があり

新しい行を除くすべての文字(デフォルト)だけでなく、すべての文字に一致します。

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

問題は、メッセージのパターンが日付グループでも一致するため、改行で折れていないときには、単に繰り返し表示されるということです。


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

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

答えて

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フラグを使用する必要があることに注意してください。

0

RegexOptionsを渡す必要があります。 Singlelineが正規表現にフラグを立てて、 "。"新しい行を除くすべての文字(デフォルト)だけでなく、すべての文字に一致します。

1

問題は、1つのメッセージが終了してから次のメッセージが開始されるタイミングを知るようにRegExパターンを終了する必要があることです。

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

問題は、マルチラインモードに入るとターミネータがないため、パターンがファイル全体をうっすらにするということです。貪欲でないものは可能な限り数文字にマッチします。

次のメッセージの日付をターミネーターとして使用すると、パーサは1行おきにしか表示されません。

パターンを終了できるファイルが他にもありますか?

2

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

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

0

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

関連する問題