2009-11-06 83 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 
... 

我想捕捉的每個數據的「塊」,使用報頭作爲一組,並且將數據作爲第二(即「COMPUTER INFO」,「計算機名:.......「)併爲每個塊重複此操作。表達式如果到目前爲止是

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

這將塊拉出到它應該的組中,這很好。但我需要讓它重複捕捉,我似乎無法得到。我試過幾個分組表達式,其中包括:

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

這似乎是正確的,但我回來很多NULL結果組與空白組項目的值。我正在使用.Net RegEx類來應用表達式,任何人都可以幫我解決這個問題嗎?

回答

12

這是不可能有重複的團體。該組將包含最後一場比賽。

您需要將其分解爲兩個問題。首先,找到每個部分:

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 2009-11-06 21:06:54

+0

在第一種情況下,你沒有得到一個組,你只是得到一個匹配。我會在示例中添加更多代碼。 – 2009-11-06 21:20:10

+0

我道歉。一個我用代碼做了這件事,它像一個魅力。我在Expresso中自己嘗試了這些例子。它必須是Singleline | Multiline選項,我將更詳細地探討這些選項,以便我能夠理解它們如何使表達式工作。非常感謝您的寶貴時間。 – Jason 2009-11-07 19:11:18

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

,或者如果你有項目之間的空行:

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

對不起...這並沒有在所有的工作。可能由於.Net解析引擎。我通過Expresso運行我的表達式來模擬。 – Jason 2009-11-06 18:50:28

1

這是我會怎麼去做。這可以讓你輕鬆獲得特定組的價值,但表達會更復雜一些。我添加換行以便於閱讀。這裏是開始:

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...) 

與Comiled,IGNORECASE,單線和CultureInvariant

然後你就可以通過組前應一致:

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

我曾考慮過這樣做,但這些團體並不是有限的。開發人員可能會在稍後添加更多的塊,或者可能會丟失一些塊。我可以確定塊組的開始,但需要處理任意數量的塊。 – Jason 2009-11-06 18:46:33