有谁知道如何拆分此文件
1 TESTAAA SERNUM A DESCRIPTION
2 TESTBBB ANOTHR ANOTHER DESCRIPTION
3 TESTXXX BLAHBL
每列有一个固定的宽度,我打算用正则表达式来做,但我不知道该怎么做。
有
{id} {firsttext} {serialhere} {description}
4 22 6 30+
有人建议使用这样的模式(。{4})(。{22})(。{6})(。+)?然后用split('')拆分它,但是用户表示这不适用于列没有价值,但即便如此,他也没有做任何例子。
我也听说过TextFieldParser,但它有一些关于性能的问题。
有谁能告诉我如何按固定宽度分割?
感谢。
答案 0 :(得分:4)
没有看到任何理由,我可能只会使用Substring
。
话虽如此,正则表达式也应该起作用。
以下示例适用于所显示的输入(而不是您给出的数字),并假设序列号是必填字段,但可能不占用其全部长度+描述是可选的。如果这些假设不正确,请按照该原则进行调整。
string input = @"1 TESTAAA SERNUM A DESCRIPTION
2 TESTBBB ANOTHR ANOTHER DESCRIPTION
3 TESTXXX BLAHBL";
var split = input.Split('\n').Select(s => new {
Id = s.Substring(0, 2),
FirstText = s.Substring(2, 13),
Serial = s.Substring(15, Math.Min(s.Length-15, 10)),
Description = s.Length > 25 ? s.Substring(25) : String.Empty
});
或者作为一个解释性示例,更明显的命名和更清晰的序列长度示例:
int idStart = 0;
int idLength = 2;
int firstTextStart = idStart + idLength;
int firstTextLength = 13;
int serialStart = firstTextStart + firstTextLength;
int serialLength = 10;
int descriptionStart = serialStart + serialLength;
var verboseSplit = input.Split('\n').Select(s => new {
Id = s.Substring(idStart, idLength),
FirstText = s.Substring(firstTextStart, firstTextLength),
Serial = s.Length > descriptionStart
? s.Substring(serialStart, serialLength)
: s.Substring(serialStart)
Description = s.Length > descriptionStart
? s.Substring(descriptionStart)
: String.Empty
});
以下任一项的输出:
Id FirstText Serial Description
1 TESTAAA SERNUM A DESCRIPTION
2 TESTBBB ANOTHR ANOTHER DESCRIPTION
3 TESTXXX BLAHBL
答案 1 :(得分:2)
根据你的样本试试这个,每个项目之间只有一个空格
{id} {firsttext} {serialhere} {description}
4 22 6 30+
string target = "1 TESTAAA SERNUM A DESCRIPTION";
List<string> result = new List<string>(Regex.Split(target, @"(.{4})(.{1})(.{22})(.{1})(.{6})(.{1})(.+)?", RegexOptions.Singleline));
答案 2 :(得分:1)
这种功能方法怎么样?
从这些数组开始:
var lines = new []
{
"1 TESTAAA SERNUM A DESCRIPTION",
"2 TESTBBB ANOTHR ANOTHER DESCRIPTION",
"3 TESTXXX BLAHBL",
};
var splits = new [] { 2, 13, 10, };
我使用的splits
与您的问题不同,因为每个示例行中字段的长度与您的分割不匹配。
现在定义一个递归函数来分割每一行:
Func<string, IEnumerable<int>, IEnumerable<string>> f = null;
f =
(t, ns) =>
{
if (ns.Any())
{
var n = ns.First();
var i = System.Math.Min(n, t.Length);
var t0 = t.Substring(0, i);
var t1 = t.Substring(i);
return new [] { t0.Trim(), }.Concat(f(t1, ns.Skip(1)));
}
else
return new [] { t.Trim(), };
};
最后,我们可以编写一个相当简单的linq查询来将它们整合在一起:
var query =
from line in lines
let fields = f(line, splits).ToArray()
select new
{
id = fields[0],
firsttext = fields[1],
serialhere = fields[2],
description = fields[3],
};
我得到的结果是: