我建议使用正则表达式来解析这些行。这是一些工作代码:
var text = @"Command sent from hmi(0).ctq[0] to calh(1).ctq[0] v:1,
Command sent from ptov(21) to bo(1).ctq[10] v:0,
Command answer from bo(1) to ptov(21) code:15 - complete,
Event ptof(1).sgn[7] v:0 s:0601,
Command sent from ptuf(1) to bo(1).ctq[5] v:0,";
var lines = text.Split(
Environment.NewLine.ToCharArray(),
StringSplitOptions.RemoveEmptyEntries
);
var regex = new Regex(@"^(?:(?<C0>Event) (?<C1>\S+) (?<C2>\S+) (?<C3>\S+)|(?<C0>Command) (?:answer|sent) from (?<C1>\S+) to (?<C2>\S+) (?<C3>.+)),$");
var result = lines
.Select(line => regex.Match(line))
.Select(
match => new {
C0 = match.Groups["C0"].Value,
C1 = match.Groups["C1"].Value,
C2 = match.Groups["C2"].Value,
C3 = match.Groups["C3"].Value
}
);
结果是:
C0 | C1 | C2 | C3 |
--------+----------------+----------------+-------- -------------+
命令 | hmi(0).ctq[0] | calh(1).ctq[0] | 诉:1 |
命令 | ptov(21) | bo(1).ctq[10] | v:0 |
命令 | 博(1) | ptov(21) | 代码:15 - 完成 |
活动 | ptof(1).sgn[7] | v:0 | s:0601 |
命令 | ptuf(1) | bo(1).ctq[5] | v:0 |
您没有指定如何解析该Command answer from
行,所以我冒昧地自己做出了一些决定。另外,我刚刚创建了一个 LINQ 查询,它将这些行解析为一系列匿名对象。请参阅下文,了解我如何将结果填充到DataTable
(稍微嘈杂的代码)中。
以下是正则表达式的一些亮点:
(?<C0>Event)
是匹配的命名组Event
。名称是C0
(第 0 列),并且在执行匹配后,可以在Match
对象中访问组的匹配值。
(?:answer|sent)
是一个非捕获组,将匹配answer
或匹配sent
但不捕获匹配的组。大部分正则表达式也由一个非捕获组组成,它将匹配Command
行或Event
行。
\S+
匹配一个或多个非空白字符。
正则表达式以^
开头和结尾以$
确保匹配整行。
要将结果放在 a 中,DataTable
您可以删除匿名类型,而是使用此代码(替换var result = lines
代码行中的 ):
var matches = lines.Select(line => regex.Match(line));
var dataTable = new DataTable();
foreach (var columnName in new[] { "A", "B", "C", "D" })
dataTable.Columns.Add(columnName);
foreach (var match in matches)
dataTable.Rows.Add(
match.Groups.Cast<Group>().Skip(1).Select(group => group.Value).ToArray()
);
唯一棘手的部分是Skip(1)
比赛中第一组被跳过的地方。第一组是整场比赛。通过跳过我知道剩下的四个组是 C0 到 C3,然后这些值用于创建包含行的列值的数组。
由于我不使用组名,它们实际上可以从正则表达式中删除。eg(?<C1>\S+)
可以用(\S+)
etc代替。
我刚刚选择了 A、B、C 和 D 作为列的随机名称。