如何在保留行结尾的同时拆分字符串?
我有一个文本块,我希望得到它的行而不会丢失最后的\ r和\ n。 现在,我有以下(次优代码):
string[] lines = tbIn.Text.Split('\n') .Select(t => t.Replace("\r", "\r\n")).ToArray();
所以我想知道 – 有更好的方法吗?
接受的答案
string[] lines = Regex.Split(tbIn.Text, @"(?<=\r\n)(?!$)");
以下似乎做了这个工作:
string[] lines = Regex.Split(tbIn.Text, @"(?<=\r\n)(?!$)");
(?<= \ r \ n)在\ r \ n之后使用'正向lookbehind'匹配而不消耗它。
(?!$)使用负前瞻来阻止输入结束时的匹配,从而避免最后一行只是一个空字符串。
使用这个正则表达式的东西:[^ \ n \ r] * \ r \ n
然后使用Regex.Matches()。 问题是你需要每个匹配中的Group(1)并从中创建你的字符串列表。 在Python中,您只需使用map()函数。 不确定在.NET中最好的方法,你从那里拿它;-)
德米特里,你的解决方案实际上非常紧凑和简单。 唯一更有效的方法是将字符串拆分字符保留在生成的数组中,但API根本不允许这样做。 因此,每个解决方案都需要迭代数组并执行某种修改(在C#中意味着每次都要分配新的字符串)。 我认为你能想到的最好的就是不重新创建数组:
string[] lines = tbIn.Text.Split('\n'); for (int i = 0; i < lines.Length; ++i) { lines[i] = lines[i].Replace("\r", "\r\n"); }
...但正如你所看到的那样看起来更麻烦! 如果性能很重要,这可能会更好一些。 如果它真的很重要,你应该考虑通过使用IndexOf()手动解析字符串,一次找到'\ r \ n的一个,然后自己创建数组。 但是,这显然是更多的代码,并且可能不是必需的。
你的解决方案和这个解决方案的一个副作用是,如果TextBox中没有一个,那么你不会在最后一行得到终止“\ r \ n”。 这是你期望的吗? 空白线怎么样?你期望它们出现在“线条”中吗?
如果您只是要替换换行符( \n
),那么执行以下操作:
string[] lines = tbIn.Text.Split('\n') .Select(t => t + "\r\n").ToArray();
编辑:Regex.Replace允许您拆分字符串。
string[] lines = Regex.Split(tbIn.Text, "\r\n") .Select(t => t + "\r\n").ToArray();
一如既往,扩展方法的好东西:)
public static class StringExtensions { public static IEnumerable SplitAndKeep(this string s, string seperator) { string[] obj = s.Split(new string[] { seperator }, StringSplitOptions.None); for (int i = 0; i < obj.Length; i++) { string result = i == obj.Length - 1 ? obj[i] : obj[i] + seperator; yield return result; } } }
用法:
string text = "One,Two,Three,Four"; foreach (var s in text.SplitAndKeep(",")) { Console.WriteLine(s); }
输出:
一,
二,
三,
四
您可以使用正则表达式实现此目的。 这是一个扩展方法:
public static string[] SplitAndKeepDelimiter(this string input, string delimiter) { MatchCollection matches = Regex.Matches(input, @"[^" + delimiter + "]+(" + delimiter + "|$)", RegexOptions.Multiline); string[] result = new string[matches.Count]; for (int i = 0; i < matches.Count ; i++) { result[i] = matches[i].Value; } return result; }
我不确定这是否是一个更好的解决方案。 你的非常紧凑和简单。