使用Dictionary 在C#中进行解析

我是编程新手,一直在努力解析文件。 我,最初试图以某种方式解析它,但这并没有最终正常工作。 我想在Dictionary 中解析以下行。

网卡:已安装7个NIC。

[01]: Broadcom Connection Name: Local Area Connection DHCP Enabled: No IP address(es) [01]: abc.de.xyz. [02]: Broadcom Connection Name: eth1 Status: Media disconnected [03]: Broadcom Connection Name: eth0 Status: Media disconnected [04]: Broadcom Connection Name: eth3 Status: Media disconnected [05]: Mellanox Connection Name: Local Area Connection 5 Status: Hardware not present [06]: Mellanox Connection Name: Local Area Connection 6 Status: Media disconnected [07]: Mellanox Connection Name: Local Area Connection 7 DHCP Enabled: No IP address(es) [01]: mno.pqr.stu.vwx 

我希望[01] Broadcom作为字典和连接名称的关键:本地连接DHCP启用:无IP地址[01]:abc.de.xyz作为其他六个的值,依此类推。 谢谢您的帮助。 真的很感激。 任何关于如何去做的帮助都会很棒,因为我疯狂阅读有关分割字符串并试图找出如何获取字典来存储值的信息。

如果您不想使用该路由,这是一个不使用正则表达式的解决方案。 此代码已经过测试。

 using System; using System.Collections.Generic; using System.IO; using System.Text; namespace NicParser { public class NicFileParser { private readonly string _file; private readonly Dictionary _nics; public NicFileParser(string file) { _file = file; _nics = new Dictionary(); } public void Parse() { var key = string.Empty; var value = new StringBuilder(); try { using (var rdr = new StreamReader(_file)) { var firstTime = true; while (rdr.Peek() > 0) { var line = rdr.ReadLine().Trim(); if (IsKey(line)) { // Once a key is hit, add the previous // key and values (except the first time). if (!firstTime) { _nics.Add(key, value.ToString()); } else { firstTime = false; } // Assign the key, and clear the previous values. key = line; value.Length = 0; } else { // Add to the values for this nic card. value.AppendLine(line); } } // Final line of the file has been read. // Add the last nic card. _nics.Add(key, value.ToString()); } } catch (Exception ex) { // Handle your exceptions however you like... } } private static bool IsKey(string line) { return (!String.IsNullOrEmpty(line) && line.StartsWith("[") && !line.Contains(".")); } // Use this to access the NIC information. public Dictionary Cards { get { return _nics; } } } } 

原谅任何可怜的C#语法 – 我已经习惯了VB .NET。 不要笑。

我会首先将文件的文本行读入字符串数组。

 foreach (string line in File.ReadLines("path-to-file")) { } 

对于每一行,您要么是“关键”行,要么是“值”行。 关键线看起来像这样:

 [01]: Broadcom 

要确定你是否在“关键”行,你可以尝试类似line.Trim().StartsWith("[") ,但是这将无法可靠地工作,因为你有其他行看起来像[01]: abc.def.ghi.jkl是IP地址,不是密钥。 所以你需要对它更聪明,甚至可能使用正则表达式来检测你是在查看IP地址还是网卡。 我不知道您正在查看的文件的确切规格,但您也可以使用前导空格/标签来帮助您确定您是否处于“键”或“值”行。

您的代码看起来像这样:

 var networkCards = new Dictionary(); string currentKey = String.Empty; foreach (string line in File.ReadLines("path-to-file")) { if ( IsKeyLine( line ) ) { currentKey = line.Trim(); networkCards.Add(currentKey, ""); } else { networkCards[currentKey] += line.Trim() + " "; } } 

需要编写IsKeyLine方法,这是整个操作的关键。 这是你可能使用的基于正则表达式的方法的一个刺:

 public bool IsKeyLine(string line) { if (!String.IsNullOrEmpty(line)) { //run two regexes - one to see if the line is of the general pattern of a "key" line //the second reg ex makes sure there isn't an ip address in the line, which would indicate that the line is part of the "value" and not the "key" return System.Text.RegularExpressions.RegEx.IsMatch(line, @"^\s*\[\d{0,2}\]: ") && !System.Text.RegularExpressions.RegEx.IsMatch(line, @"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"); } return false; } 

现在,我没有花时间测试任何代码 – 这是我的头脑。 但至少应该让你走向正确的方向。 确定最重要的是文件格式的标准。 这将为您提供走正路的线索。 您可能甚至不需要正则表达式(这是更可取的,因为正则表达式通常很昂贵)。

您还可以计算每行开头的制表符/空格,指示该行所属的位置。

考虑利用领先的空白区域来确定线路所扮演的“角色”(嘿,Python会这样做;-)。 然后可以使用简单的状态机逐行解析文件。

我怀疑,由于这是生成输出,因此可以可靠地使用此方法。 如果是这种情况,它会极大地简化规则和解析。

快乐的编码。


这是一个小概念validation,用于确定生产线的“角色”。

 using (var inp = ...) { string line; while ((line = inp.ReadLine()) != null) { // normalize to our world of 8-space tabs line = line.Replace("\t", " "); var lineDepth = line.Length - line.TrimStart().Length; if (lineDepth < 65) { // is potential "heading line" } else { // >= 65 // is "property line" } } } 

我知道,这个问题是关于C#,而不是关于PowerShell ,并且已经有一些很好的C#答案,我仍然想提供一个PowerShell解决方案,作为需要考虑的事情。 它可以比c#代码更简单,但这取决于观点:

 $networkCards = systeminfo | ForEach-Object {$a=0} { if ($_.startswith("Network Card(s)")) {$a=1} else {if ($a) {$_}} } $networkCards | ForEach-Object {$data=@{}} { if ($_.trim().startswith("[")) { $c = $_.trim(); $data[$c] = @()} else {$data[$c] += $_.trim() } } #Now we have a hash table with the keys as requested in the question #and the values are lists of separate strings, but those can be easily #concatenated if needed. Let's display it: $data 

如果你安装了powershell (它现在是Windows 7的一部分)你可以打开它并在命令提示符下粘贴上面的代码,你就能立即看到结果。

如果将它放在csv输出中,可能会更容易。

 Systeminfo /fo csv