Это не очень хорошая идея делать с Regex, потому что довольно легко забыть крайние случаи, не легко понять и не легко отладить. Это довольно легко попасть в ситуацию, когда Regex зависает ваш процессор и время ожидания. (Я пока не могу комментировать другие ответы. Поэтому, пожалуйста, проверьте, по крайней мере, мои два других случая, прежде чем выбрать окончательное решение.)
В ваших случаях для вашего примера работает следующее решение Regex. Однако существуют некоторые дополнительные ограничения: Вам необходимо убедиться, что в столбце без начального или бесконечного столбца нет пустых значений. Или, скажем, если есть более двух столбцов, и любой из них в середине пуст, из-за этого имена и значения этой строки не будут совпадать.
К сожалению, я не могу дать вам решение не-Regex, потому что я не знаю спецификацию, например: будут ли пустые места? Будут ли там вкладки? У каждого поля есть фиксированное количество символов, или они будут гибкими? Если он гибкий и может иметь пустые значения, какие правила обнаруживать, какие столбцы пусты? Я предполагаю, что вполне возможно, что они определяются длиной имени столбца и будут иметь только пробел в качестве разделителя. Если это так, то есть два способа решить эту проблему: два прохода Regex или написать свой собственный парсер. Если бы все поля имели фиксированную длину, это было бы еще проще: просто используя подстроку, чтобы обрезать линии, а затем обрезать их.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
public class Program
{
public class Record{
public string Name {get;set;}
public string Value {get;set;}
}
public static void Main()
{
var regex = new Regex(@"(?<name>((?!-)[\w]+[ ]?)*)(?>(?>[ \t]+)?(?<name>((?!-)[\w]+[ ]?)+)?)+(?:\r\n|\r|\n)(?>(?<splitters>(-+))(?>[ \t]+)?)+(?:\r\n|\r|\n)(?<value>((?!-)[\w]+[ ]?)*)(?>(?>[ \t]+)?(?<value>((?!-)[\w]+[ ]?)+)?)+", RegexOptions.Compiled);
var testingValue =
@"EMAIL STARTING IN APRIL
Marketing ID Local Number
------------------- ----------------------
GR332230 0000232323
Dispatch Code Logic code
----------------- -------------------
GX3472 1
Destination ID Destination details
----------------- -------------------
3411144";
var matches = regex.Matches(testingValue);
var rows = (
from match in matches.OfType<Match>()
let row = (
from grp in match.Groups.OfType<Group>()
select new {grp.Name, Captures = grp.Captures.OfType<Capture>().ToList()}
).ToDictionary(item=>item.Name, item=>item.Captures.OfType<Capture>().ToList())
let names = row.ContainsKey("name")? row["name"] : null
let splitters = row.ContainsKey("splitters")? row["splitters"] : null
let values = row.ContainsKey("value")? row["value"] : null
where names != null && splitters != null &&
names.Count == splitters.Count &&
(values==null || values.Count <= splitters.Count)
select new {Names = names, Values = values}
);
var records = new List<Record>();
foreach(var row in rows)
{
for(int i=0; i< row.Names.Count; i++)
{
records.Add(new Record{Name=row.Names[i].Value, Value=i < row.Values.Count ? row.Values[i].Value : ""});
}
}
foreach(var record in records)
{
Console.WriteLine(record.Name + " = " + record.Value);
}
}
}
выход:
Marketing ID = GR332230
Local Number = 0000232323
Dispatch Code = GX3472
Logic code = 1
Destination ID = 3411144
Destination details =
Обратите внимание, что это также работает для такого рода сообщений:
Электронная почта, начинающаяся в апреле
Marketing ID Local Number
------------------- ----------------------
GR332230 0000232323
Dispatch Code Logic code
----------------- -------------------
GX3472 1
Destination ID Destination details
----------------- -------------------
3411144
выход:
Marketing ID = GR332230
Local Number = 0000232323
Dispatch Code = GX3472
Logic code = 1
Destination ID =
Destination details = 3411144
Или это:
EMAIL STARTING IN APRIL
Marketing ID Local Number
------------------- ----------------------
Dispatch Code Logic code
----------------- -------------------
GX3472 1
Destination ID Destination details
----------------- -------------------
3411144
выход:
Marketing ID =
Local Number =
Dispatch Code = GX3472
Logic code = 1
Destination ID =
Destination details = 3411144