2009-11-06 18 views
7

ログファイルを読み込み、正規表現を使用してマシン/設定情報を抽出しようとしています。ここでは、ログからのサンプルは次のとおりです。正規表現 - 繰り返しグループ

... 
COMPUTER INFO: 
Computer Name:     TESTCMP02 
Windows User Name:    testUser99 
Time Since Last Reboot:  405 Minutes 
Processor:      (2 processors) Intel(R) Xeon(R) CPU   5160 @ 3.00GHz 
OS Version:     5.1 .number 2600:Service Pack 2 
Memory:      RAM: 48% used, 3069.6 MB total, 1567.3 MB free 
ServerTimeOffSet:    -146 Seconds 
Use Local Time for Log:  True 

INITIAL SETTINGS: 
Command Line:     /SKIPUPDATES 
Remote Online:     True 
INI File:      c:\demoapp\system\DEMOAPP.INI 
DatabaseName:     testdb 
SQL Server:     10.254.58.1 
SQL UserName:     SQLUser 
ODBC Source:     TestODBC 
Dynamic ODBC (not defined): True 
... 

私は「、第二(すなわち「コンピュータINFO」として、各データの「ブロック」、一つのグループとしてのヘッダを使用して、データをキャプチャするためにコンピュータ名を希望します:....... ")、ブロックごとにこれを繰り返します。式がこれまであった場合は

(?s)(\p{Lu}{1,} \p{Lu}{1,}:\r\n)(.*\r\n\r\n) 

このようにして、ブロックをグループに引き出します。これはすばらしいです。しかし、私はそれがキャプチャを繰り返す必要があります、私は得ることができないようです。私はいくつかのグループ化式を、試してみた:正しいように見えるが、私は戻って空のグループの項目値とNULL結果グループの多くを得るでしょう

(?s)(?:(\p{Lu}{1,} \p{Lu}{1,}:\r\n)(.*\r\n\r\n))* 

。私は式を適用するために.NET RegExクラスを使用しています。

答えて

12

持ってすることはできません繰り返されるグループ。グループには最後の試合が含まれます。

これには2つの問題があります。まず、各セクションを見つける:

new Regex(@"(?>^[A-Z\s]+:\s*$)\s*(?:(?!^\S).)*", RegexOptions.Singleline | RegexOptions.Multiline); 

をそして、各試合の中、グループに各フィールド/値と一致するように、別の正規表現を使用します。

new Regex(@"^\s+(?<name>[^:]*):\s*(?<value>.*)$", RegexOptions.Multiline); 

になりますこれを使用するコードを

Regex sectionRegex = new Regex(@"(?>^[A-Z\s]+:\s*$)\s*(?:(?!^\S).)*", RegexOptions.Singleline | RegexOptions.Multiline); 
Regex nameValueRegex = new Regex(@"^\s+(?<name>[^:]*):\s*(?<value>.*)$", RegexOptions.Multiline); 
MatchCollection sections = sectionRegex.Matches(logData); 
foreach (Match section in sections) 
{ 
    MatchCollection nameValues = nameValueRegex.Matches(section.ToString()); 
    foreach (Match nameValue in nameValues) 
    { 
     string name = nameValue.Groups["name"].Value; 
     string value = nameValue.Groups["value"].Value; 
     // OK, do something here. 
    } 
} 
+0

私はこのアプローチを理解していますが、最初の式が一致するグループを返していないため、理由がわかりません。助言がありますか? – Jason

+0

最初のケースでは、あなたはグループを取得していない、あなたはちょうど一致している。この例にコードを追加します。 –

+0

私は謝る。私はこれをコードで行いました。それは魅力的でした。私はExpressoで例を試していました。これは、Singleline | Multilineオプションでなければなりません。これは、式をどのように動作させるかを理解できるように、より詳細に調べなければなりません。あなたのお時間をありがとうございました。 – Jason

1
((?<header>[^:]+:)(?<content>[^\r\n]+)?\r\n)+ 

か、あなたは項目間の空行がある場合:ここで

(((?<header>[^:]+:)(?<content>[^\r\n]+)?\r\n)|\r\n)+ 
+0

申し訳ありません...まったく動作しませんでした。おそらく、.Net解析エンジンが原因です。 Expressoで表現を実行してシミュレーションしています。 – Jason

1

を、私はそれについて移動する方法をです。これにより、特定のグループの価値を簡単に得ることができますが、表現は少し複雑になります。読みやすくする改行を追加します。 Comiled、IGNORECASE、単一行、およびCultureInvariant

その後

あなたはグループの元を経由して、これを一致させることができるだろうと

COMPUTER INFO:.*Computer Name:\s*(?<ComputerName>[\w\s]+).*Windows User Name:\s*(?<WindowUserName>[\w\s]+).*Time Since Last Reboot:\s*(?<TimeSinceLastReboot>[\w\s]+).* (?# This continues on through each of the lines...) 

:ここで開始です

string computerName = match.Group["ComputerName"].Value; 
string windowUserName = match.Group["WindowUserName"].Value; 
// etc. 
+0

私はそれについて考えていましたが、グループは有限ではありません。開発者は後でブロックを追加したり、一部のブロックが不足している可能性があります。私は、ブロックのグループの開始を識別することができますが、それらの任意の数を処理する必要があります。 – Jason

関連する問題