【问题标题】:How to split a string while preserving line endings?如何在保留行尾的同时拆分字符串?
【发布时间】:2009-01-29 17:58:34
【问题描述】:

我有一个文本块,我想得到它的行而不丢失最后的 \r 和 \n。现在,我有以下(次优代码):

string[] lines = tbIn.Text.Split('\n')
                     .Select(t => t.Replace("\r", "\r\n")).ToArray();

所以我想知道 - 有没有更好的方法呢?

接受的答案

string[] lines =  Regex.Split(tbIn.Text, @"(?<=\r\n)(?!$)");

【问题讨论】:

    标签: c# .net string split


    【解决方案1】:

    以下似乎可以完成这项工作:

    string[] lines =  Regex.Split(tbIn.Text, @"(?<=\r\n)(?!$)");
    

    (?

    (?!$) 使用负前瞻来防止在输入末尾匹配,从而避免最后一行只是一个空字符串。

    【讨论】:

    • 哦……我的……上帝。这是极好的。公认!谢谢! (我希望我能这么聪明。)
    【解决方案2】:

    类似于使用这个正则表达式的东西: [^\n\r]*\r\n

    然后使用 Regex.Matches()。 问题是您需要 Group(1) 从每个匹配项中创建您的字符串列表。在 Python 中,您只需使用 map() 函数。不确定在 .NET 中执行此操作的最佳方法,您可以从那里获取 ;-)

    【讨论】:

      【解决方案3】:

      Dmitri,您的解决方案实际上非常简洁明了。唯一更有效的方法是在生成的数组中保留字符串拆分字符,但 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,然后自己创建数组。不过,这要多得多的代码,而且可能没有必要。

      您的解决方案和这个解决方案的副作用之一是您不会在最后一行获得终止“\r\n”(如果有)文本框中还没有一个。这是你所期望的吗?那么空行呢……您希望它们出现在“行”中吗?

      【讨论】:

        【解决方案4】:

        如果您只是要替换换行符 (\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();
        

        【讨论】:

        • 这会导致我最后有 \r\r\n :(
        • 我不明白你的意思 - 你的原始字符串是什么样的?
        • 啊 - 我想我现在看到了问题 - 我虽然你正在将 linux 样式的换行符 (\n) 转换为 windows (\r\n)。我会研究和编辑我的帖子。
        【解决方案5】:

        一如既往,扩展方法的好东西:)

        public static class StringExtensions
        {
            public static IEnumerable<string> 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);
                }
        

        输出:

        一个,

        两个,

        三个,

        四个

        【讨论】:

          【解决方案6】:

          您可以使用正则表达式来实现这一点。这是一个扩展方法:

              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;
              }
          

          我不确定这是否是更好的解决方案。你的非常紧凑和简单。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-06-29
            • 1970-01-01
            • 2014-02-11
            • 2013-08-08
            • 1970-01-01
            • 2023-04-02
            相关资源
            最近更新 更多