字符串分隔C#
本文关键字:分隔 字符串 | 更新日期: 2023-09-27 18:24:18
我正在读取如下的txt文件。我正试图将这些数据分成几个不同的列。
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,
我能用长矛把这句话从"事件"开始。我是这样做的。这很容易,因为它在每个重要部分后面都有空白字符。
List<string> description = list.Select(x => x.System_Description).ToList<string>();
DataTable dt = new DataTable();
dt.Columns.Add("values");
foreach(string items in description)
{
if (items[0] == 'E')
{
string[] _columns = items.Split(" ".ToCharArray());
}
else
{
}
DataRow row = dt.NewRow();
dt.Rows.Add(items);
在这一行中,从"命令"开始,我想把它分成4列。第一个将只是"命令",第二个我想把一切都放在"从"answers"到"之间。第三个将是"to"之后的数据,最后一个将是带"v:.."的值。你能帮我吗,或者建议我怎么做?
我建议使用正则表达式来解析这些行。以下是一些工作代码:
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]| v:1|命令| ptov(21)| bo(1).ctq[10]| v:0|命令| bo(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
(噪声稍大的代码)中。
以下是正则表达式的一些亮点:
CCD_ 3是与CCD_ 4匹配的命名组。名称为
C0
(列零),并且在执行匹配之后,可以在Match
对象中访问组的匹配值。(?:answer|sent)
是将与answer
或sent
匹配但不捕获其匹配的非捕获组。正则表达式的主体也由一个非捕获组组成,该组将与Command
行或Event
行相匹配。'S+
匹配一个或多个非空白字符。以
^
开始正则表达式,以$
结束正则表达式,确保整行匹配。
要将结果放入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,然后这些值用于创建具有行的列值的数组。
由于我不使用组名,所以它们实际上可以从正则表达式中删除。例如(?<C1>'S+)
可以替换为('S+)
等
我只是选择了A、B、C和D作为列的随机名称。
您可以尝试使用该字符串。Split方法将字符串拆分为一个数组,使用空格(")作为拆分字符。然后,根据您的示例文件外观,您可以简单地使用数组中的正确索引来获得所需的列。
var li = s.Split(',')
.ToList()
.Where(
x=>
x.Split(' ')[0].Trim() == "Command"
)
.Select(
x => new
{
Command = x.Split(' ')[0],
Direction = x.Split(' ')[1],
From = x.Split(' ')[3],
To = x.Split(' ')[5] ,
v = x.Split(' ')[6]
})
.ToList();