在 C# 中使用字典<字符串、字符串>进行分析
本文关键字:字符串 字典 | 更新日期: 2023-09-27 17:56:47
我是编程新手,一直在努力解析文件。我最初试图以某种方式解析它,但最终无法正常工作。我想解析字典中的以下行<字符串,字符串> .
网卡:已安装 7 个网卡。
[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<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; }
}
}
}
原谅任何糟糕的 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, 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() + " ";
}
}
需要编写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 确实如此;-)。然后,可以使用简单的状态机逐行解析文件。
我怀疑,由于这是生成的输出,因此可以可靠地使用此方法。如果是这种情况,它大大简化了规则和解析。
快乐编码。
这是一个确定生产线"角色"的小概念验证。
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