簡體   English   中英

枚舉正則表達式匹配名稱/值

[英]Enumerate regex match names/values

該偽代碼的C#等效項是什么?

var pattern = ...;
var lookup = new Dictionary<string, string>();

foreach (var group in new Regex(pattern).Matches())
{
    lookup[group.Name] = group.Value;
}

我沒有看到任何公開組名稱的與System.Text.RegularExpressions組相關的對象。

我想念什么?

我實際上想做的是用這種格式的行轉換文件:

eventName|message|date

IEnumerable<EventLogLine> ,其中EventLogLine為:

public struct EventLogLine
{
    public string EventName { get; set; }
    public string Message { get; set; }
    public DateTime Date { get; set; }
}

並將這些行放入IDictionary<string /*EventName*/, IEnumerable<EventLogLine>>.

為了更直接地回答您的原始問題(不對您的方法發表評論),因為我遇到了類似的問題...

根據Mono的源代碼Groups索引器的枚舉基於私有的Match.regex字段,因此您仍然需要Regex 但是,如果您這樣做,就像您在上面一樣...

public static Dictionary<string, string> ToDictionary(
    Regex regex, GroupCollection groups)
{
    var groupDict = new Dictionary<string, string>();
    foreach (string name in regex.GetGroupNames()){ //the only way to get the names
        Group namedGroup = groups[name]; //test for existence
        if (namedGroup.Success)
            groupDict.Add(name, namedGroup.Value);
    }
    return groupDict;
}

或者,作為Linq,

regex.GetGroupNames()
  .Where(name => groups[name].Success)
  .ToDictionary(name => name, name => groups[name].Value)

我只是在使用LINQ時才提出來。 它依賴於List<string>用文件中的行填充。

        var lines = new List<string>();
        var dict = lines.Select(l =>
        {
            var sp = l.Split('|');
            return new EventLogLine { EventName = sp[0], Message = sp[1], Date = DateTime.Parse(sp[2]) };
        })
        .GroupBy(e => e.EventName)
        .ToDictionary(grp => grp.Key, grp => grp.AsEnumerable());

基本上,您可以使用Select()將每一行轉換為EventLogLine ,然后使用GroupBy()基於EventName創建分組,然后使用ToDictionary()運行查詢並以所需格式創建字典!

請參閱Match.Groups MSDN文章中的示例 我認為您應該查看Alastair的答案,因為您輸入的內容非常簡單,如果您僅使用ReadLine和Split,則稍后閱讀代碼可能會更容易。

考慮使用ToLookup而不是ToDictionary 通常,查找是不可變的,並且公開了一個非常簡單的API,從而可以自然地與linq和通用代碼一起工作。 另外,我會將解析封裝到EventLogLine結構中。

結果,代碼如下所示:

IEnumerable<string> lines;

ILookup<string, EventLogLine> lookup = 
    lines.Select(EventLogLine.Parse).ToLookup(evtLine => evtLine.EventName);

消費者示例:

if(lookup["HorribleEvent"].Any())
    Console.WriteLine("OMG, Horrible!");

foreach(var evt in lookup["FixableEvent"])
    FixIt(evt);

var q = from evtName in relevantEventNames
        from evt in lookup[evtName]
        select MyProjection(evt);

請注意,與字典不同,您不需要檢查密鑰是否存在:

if(dictionary.ContainsKey("HorribleEvent")) //&& dictionary["HorribleEvent"].Any() sometimes needed
    Console.WriteLine("OMG, Horrible!");

if(dictionary.ContainsKey("FixableEvent"))
    foreach(var evt in lookup["FixableEvent"])
        FixIt(evt);

var q = from evtName in relevantEventNames.Where(dictionary.ContainsKey)
        from evt in dictionary[evtName]
        select MyProjection(evt);

您可能會注意到,使用包含IEnumerable值的字典會產生細微的摩擦-ILookup是您想要的!

最后,修改后的EventLogLine

public struct EventLogLine {
    public string EventName { get; private set; }
    public string Message { get; private set; }
    public DateTime Date { get; private set; }

    public static EventLogLine Parse(string line) {
        var splitline = line.Split('|');
        if(splitline.Length != 3) throw new ArgumentException("Invalid event log line");
        return new EventLogLine { 
            EventName = splitline[0],
            Message = splitline[1],
            Date = DateTime.Parse(splitline[2]),
        };
    }
}

要回答問題的這一部分:

我沒有看到任何公開組名稱的與System.Text.RegularExpressions組相關的對象。 我想念什么?

我已經改編了Eamon Nerbonne的結構以使用正則表達式:

public struct EventLogLine
{
    public string EventName { get; private set; }
    public string Message { get; private set; }
    public DateTime Date { get; private set; }

    private static Regex expectedLineFormat = new Regex(
            @"^(?<eventName>[^|]*)\|(?<message>[^|]*)\|(?<date>[^|]*)$",
            RegexOptions.Singleline | RegexOptions.Compiled
    );

    public static EventLogLine Parse(string line) {

        Match match = expectedLineFormat.Match(line);

        if (match.Success) {
            return new EventLogLine {
                EventName = match.Groups["eventName"].ToString(),
                Message = match.Groups["message"].ToString(),
                Date = DateTime.Parse(match.Groups["date"].ToString()
            };
        }
        else {
            throw new ArgumentException("Invalid event log line");
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM