Analysis in C # with the dictionary <string, string>
I am new to programming and try to parse the file. At first I tried to parse it in a certain way, but it did not finish working correctly. I want to parse the next line in the dictionary <string, string>.
Network Card (s): 7 Network Adapters Installed.
[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 I want Broadcom as the key to the dictionary and the connection name: LAN connection DHCP is enabled: no IP addresses (s) [01]: abc.de.xyz as the value, etc. for the other six, thanks for the help. Really appreciate it. Any help on how to do this would be great since I went crazy reading about line breaks and tried to figure out how to get the dictionary to store the value.
Here is a solution that does not use regex if you do not want to use this route. This code has been tested.
using System; using System.Collections.Generic; using System.IO; using System.Text; namespace NicParser { public class NicFileParser { private readonly string _file; private readonly Dictionary<string, string> _nics; public NicFileParser(string file) { _file = file; _nics = new Dictionary<string, string>(); } 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<string, string> Cards { get { return _nics; } } } } Forgive any bad C # syntax - I'm used to VB.NET. Do not laugh.
I first read the lines of lines of text in an array of lines.
foreach (string line in File.ReadLines("path-to-file")) { } For each line, you are either in the line "key" or in the line "value". The key lines are as follows:
[01]: Broadcom To determine if you are on the key line, you can try something like line.Trim().StartsWith("[") , but this will not work reliably because you have other lines that look like [01]: abc.def.ghi.jkl , which are IP addresses and are not keys. Therefore, you need to be a little smarter about this and perhaps even use a regular expression to determine if you are looking at an IP address or network card. I don’t know the exact characteristics of the file you are looking at, but you can also use leading spaces / tabs to help you determine if you are in the “key” or “value” line.
Then your code will look something like this:
var networkCards = new Dictionary<String, String>(); 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() + " "; } } The IsKeyLine method must be written and is the main part of the whole operation. Here you can use the regex method, which you can use:
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; } Now I have not found the time to check any of this code - it is not in my head. But that should at least make you go in the right direction. However, the most important thing is to define a standard for the file format. This will give you tips to go the right way. You might not even need regular expressions (which would be preferable, since regular expressions usually run expensive).
Think about using a leading white space to define the “role” the line plays (hey, Python does ;-). The file can then be analyzed in turn using a simple state machine.
I suspect that since this is the generated output, this method can be reliably used. If so, it greatly simplifies rules and parsing.
Happy coding.
Here is a little proof of concept for defining the "role" of a string.
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" } } } I know this question is about C #, not powershell , and there are already some good answers in C #, but I would like to contribute to the powershell solution as something to consider. This may turn out to be simpler than C # code, but it depends on the point of view:
$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 display it: $data If you have installed powershell (now it is part of Windows 7), you can open it and paste the above code on the command line, and you can immediately see the result.