Парсинг столбцов текстового файла
Каким способом можно спарсить столбцы и добавить их в класс. А затем к ним обратиться по мере надобности
public class Detail
{
public string Ch { get; set; }
public string Type { get; set; }
public string Duplex { get; set; }
public string Speed { get; set; }
public string Neg { get; set; }
...
}
Пример данных, которые нужно спарсить:
Ch Type Duplex Speed Neg control State Port Mode (VLAN)
-------- ------- ------ ----- -------- ------- ------------- ------------------------
Po1 -- -- -- -- -- Not Present Access (1)
Po2 -- -- -- -- -- Not Present Access (1)
Po3 -- -- -- -- -- Not Present Access (1)
Po4 -- -- -- -- -- Not Present Access (1)
Дополнение
Видел в интернет что то подобное, но это не работает. Не знаю как обратиться к неинициализированному объекту
Parse(log, ' ');
public IEnumerable<Detail> Parse(string source, char delimiter)
{
return source.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Skip(1)
.Select(x =>
{
var detail = x.Split(new[] { delimiter });
return new Detail
{
Ch = detail[0],
Type = detail[1],
Duplex = detail[2],
Speed = detail[3],
Neg = detail[4]
};
});
}
Ответы (2 шт):
Автор решения: motpfofs
→ Ссылка
Я немного поправил код, который вы предложили. Это однозначно не самое оптимальное решение и я уверен, что предложат лучше, но всё же:
- С помощью регулярных выражений заменяем все пробелы (которые идут подряд больше двух) на определённый нами сепаратор
- Разбиваем строку используя наш сепаратор
public static IEnumerable<Detail> ParseLog(string source)
{
return source.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Skip(2)
.Select(x =>
{
RegexOptions options = RegexOptions.None;
Regex regex = new Regex("[ ]{2,}", options);
x = regex.Replace(x, "#sep#");
var detail = x.Split("#sep#");
return new Detail
{
Ch = detail[0].Trim(),
Type = detail[1].Trim(),
Duplex = detail[2].Trim(),
Speed = detail[3].Trim(),
Neg = detail[4].Trim()
};
});
}
Автор решения: aepot
→ Ссылка
Немного монструозно получилось, но решал без регулярок и в лоб. На гениальность не претендую.
class Program
{
static void Main(string[] args)
{
string text = @"Ch Type Duplex Speed Neg control State Port Mode (VLAN)
-------- ------- ------ ----- -------- ------- ------------- ------------------------
Po1 -- -- -- -- -- Not Present Access (1)
Po2 -- -- -- -- -- Not Present Access (1)
Po3 -- -- -- -- -- Not Present Access (1)
Po4 -- -- -- -- -- Not Present Access (1) ";
foreach (Detail d in ParseLog(text))
Console.WriteLine(d);
Console.ReadKey();
}
public static IEnumerable<Detail> ParseLog(string source)
{
string[] lines = source.Replace(Environment.NewLine, "\n").Split('\n');
List<(int, int)> columnsIndex = new List<(int, int)>();
int start = 0;
bool isHeader = false;
for (int i = 0; i < lines[1].Length; i++)
{
if (!isHeader && lines[1][i] == '-')
{
start = i;
isHeader = true;
}
else if (isHeader && (lines[1][i] == ' ' || i == lines[1].Length - 1))
{
columnsIndex.Add((start, i - start));
isHeader = false;
}
}
foreach (string line in lines.Skip(2))
{
List<string> values = new List<string>();
foreach ((int offset, int length) in columnsIndex)
{
values.Add(line.Substring(offset, offset + length > line.Length ? line.Length - offset : length).Trim());
}
if (values.Count > 7)
yield return new Detail
{
Ch = values[0],
Type = values[1],
Duplex = values[2],
Speed = values[3],
Neg = values[4],
Control = values[5],
State = values[6],
PortMode = values[7],
};
}
}
}
public class Detail
{
public string Ch { get; set; }
public string Type { get; set; }
public string Duplex { get; set; }
public string Speed { get; set; }
public string Neg { get; set; }
public string Control { get; set; }
public string State { get; set; }
public string PortMode { get; set; }
public override string ToString()
=> string.Join(", ", GetType().GetProperties().Select(x => x.GetValue(this)));
}
Вывод в консоль
Po1, --, --, --, --, --, Not Present, Access (1)
Po2, --, --, --, --, --, Not Present, Access (1)
Po3, --, --, --, --, --, Not Present, Access (1)
Po4, --, --, --, --, --, Not Present, Access (1)