【问题标题】:Normalize newlines in C#在 C# 中规范化换行符
【发布时间】:2008-09-26 17:48:59
【问题描述】:

我有一个可能包含 \r、\n、\r\n、\n\r 或它们的任意组合的数据流。有没有一种简单的方法来规范化数据,让它们都变成\r\n对,让显示更加一致?

所以会产生这种翻译表的东西:

\r     --> \r\n
\n     --> \r\n
\n\n   --> \r\n\r\n
\n\r   --> \r\n
\r\n   --> \r\n
\r\n\n --> \r\n\r\n

【问题讨论】:

  • 等等,所以你想让 \n\r 映射到 \r\n 吗?那不是标准化。没有通用平台使用 \n\r 作为行尾。
  • 不是说平台正常,现在是吗?我已经看到了具有这种方式的数据(特别是来自 VB 代码)代码,我需要考虑它。抱歉,如果这不符合“规范化”的严格定义,但肯定符合我需要处理的数据的定义,这就是重点

标签: c# .net


【解决方案1】:

我相信这会满足您的需求:

using System.Text.RegularExpressions;
// ...
string normalized = Regex.Replace(originalString, @"\r\n|\n\r|\n|\r", "\r\n");

我不能 100% 确定确切的语法,而且我没有方便检查的 .Net 编译器。我用 perl 编写了它,并将其转换为(希望是正确的)C#。唯一真正的技巧是首先匹配“\r\n”和“\n\r”。

要将其应用于整个流,只需在输入块上运行。 (如果你愿意,你可以使用流包装器来做到这一点。)


原来的perl:

$str =~ s/\r\n|\n\r|\n|\r/\r\n/g;

测试结果:

[bash$] ./test.pl
\r -> \r\n
\n -> \r\n
\n\n -> \r\n\r\n
\n\r -> \r\n
\r\n -> \r\n
\r\n\n -> \r\n\r\n

更新:现在将 \n\r 转换为 \r\n,尽管我不会称之为规范化。

【讨论】:

  • 这个不符合上表中例子的要求。。看我修改的正则表达式,需要考虑\n\n。
  • 这个很接近,但是 \n\r 应该简单地将元素交换为 \r\n(从 VB 开发人员的代码中看到此输入)
  • 好的,进行了更改。我不会考虑这种标准化,但添加到正则表达式中很容易。
  • 您需要从替换字符串中删除“@”。如果您不这样做,它将用 '\\r\\n' 替换 '\r\n',因为您要求的是文字字符串“\r\n”。更好的是用 Environment.NewLine 常量替换。
  • 感谢您了解,NerdFury。我从替换字符串中删除了@。我会将其更改为 NewLine 常量,但由于他特别要求“\r\n”,我想我应该不理会它。
【解决方案2】:

我和 Jamie Zawinski 一起讨论 RegEx:

“有些人在遇到问题时会想“我知道,我会使用正则表达式。”现在他们有两个问题”

对于我们这些喜欢可读性的人:

  • 第一步

    用\n替换\r\n

    将\n\r替换为\n(如果你真的想要这个,有些发帖人似乎不这么认为)

    将 \r 替换为 \n

  • 步骤 2 将 \n 替换为 Environment.NewLine 或 \r\n 或其他任何内容。

【讨论】:

  • 这是一个简单的正则表达式。如果是 HTML 解析,我会同意你的看法。
  • @cchamberlain 你的意思是stackoverflow.com/a/1732454/461444 ? :D
  • @AFract 是的。 :
【解决方案3】:

正常化中断,所以它们都是\r\n

var normalisedString =
            sourceString
            .Replace("\r\n", "\n")
            .Replace("\n\r", "\n")
            .Replace("\r", "\n")
            .Replace("\n", "\r\n");

【讨论】:

    【解决方案4】:

    这是一个两步过程。
    首先将\r\n 的所有组合转换为一个组合,例如\r
    然后将所有\r 转换为目标\r\n

    normalized = 
        original.Replace("\r\n", "\r").
                 Replace("\n\r", "\r").
                 Replace("\n", "\r").
                 Replace("\r", "\r\n"); // last step
    

    【讨论】:

      【解决方案5】:

      Regex 会有所帮助.. 可以做大致这样的事情..

      (\r\n|\n\n|\n\r|\r|\n) 替换为\r\n

      这个正则表达式从发布的表格中产生了这些结果(只是测试左侧),所以替换应该正常化。

      \r   => \r 
      \n   => \n 
      \n\n => \n\n 
      \n\r => \n\r 
      \r\n => \r\n 
      \r\n => \r\n 
      \n   => \n 
      

      【讨论】:

      • 除非它已经包含 \r\n,否则替换会将其扩展为 \r\n\r\n。 \n\r 也一样。我相信答案是神秘的正则表达式语言,但对我来说这是一门黑魔法。
      • CQ,这不符合他的要求。正则表达式可能有效,但不像您发布的那样。
      • 同意我没有考虑现有的\r\n
      • 这就是为什么我粗略地说的原因,像在 \r\n 之前进行一些调整可能会解决这个问题。
      【解决方案6】:

      你想得太复杂了。 忽略每一个\r,把每一个\n变成一个\r\n。

      在伪 C# 中:

      char[] chunk = new char[X];
      StringBuffer output = new StringBuffer();
      
      buffer.Read(chunk);
      foreach (char c in chunk)
      {
         switch (c)
         {
            case '\r' : break; // ignore
            case '\n' : output.Append("\r\n");
            default   : output.Append(c);
         }
       }
      

      编辑:单独的 \r 不是行终止符,所以我怀疑你真的想将 \r 扩展为 \r\n。

      【讨论】:

      • 他想让独立的\r也变成\r\n。
      • 嗯。不敢相信他真的想要那个:)
      • Mac 在 MacOS 9 之前使用 CR 进行换行。\n\r 让我感到惊讶。
      • MacOS X 之前的 Mac 和 80 年代的一些 8 位系统使用 CR。 MacOS X 像任何其他 Unix 系统一样使用 LF
      • 只是指出我们正在将各种代码移植到各种语言和平台。代码是由数百人编写的,其中一些人现在可能已经死了。并且拼写错误的数量“\n\r”只是......令人难以置信的高......这是一个极端情况是的,不是每个人都使用其他语言中涉及大量字符串数据的逻辑......我猜,但是“\n\r " 在我们的案例中检查是 1000% 值得的。
      【解决方案7】:

      这是问题的答案。给定的解决方案用给定的翻译表替换字符串。 它不使用昂贵的正则表达式函数。 它也不使用多个替换函数,每个替换函数都通过多次检查等对数据进行循环。

      所以搜索是直接在 1 for 循环中完成的。对于必须增加结果数组容量的次数,Array.Copy 函数中也使用了循环。这就是所有的循环。 在某些情况下,更大的页面大小可能更有效。

      public static string NormalizeNewLine(this string val)
      {
          if (string.IsNullOrEmpty(val))
              return val;
      
          const int page = 6;
          int a = page;
          int j = 0;
          int len = val.Length;
          char[] res = new char[len];
      
          for (int i = 0; i < len; i++)
          {
              char ch = val[i];
      
              if (ch == '\r')
              {
                  int ni = i + 1;
                  if (ni < len && val[ni] == '\n')
                  {
                      res[j++] = '\r';
                      res[j++] = '\n';
                      i++;
                  }
                  else
                  {
                      if (a == page) //ensure capacity
                      {
                          char[] nres = new char[res.Length + page];
                          Array.Copy(res, 0, nres, 0, res.Length);
                          res = nres;
                          a = 0;
                      }
      
                      res[j++] = '\r';
                      res[j++] = '\n';
                      a++;
                  }
              }
              else if (ch == '\n')
              {
                  int ni = i + 1;
                  if (ni < len && val[ni] == '\r')
                  {
                      res[j++] = '\r';
                      res[j++] = '\n';
                      i++;
                  }
                  else
                  {
                      if (a == page) //ensure capacity
                      {
                          char[] nres = new char[res.Length + page];
                          Array.Copy(res, 0, nres, 0, res.Length);
                          res = nres;
                          a = 0;
                      }
      
                      res[j++] = '\r';
                      res[j++] = '\n';
                      a++;
                  }
              }
              else
              {
                  res[j++] = ch;
              }
          }
      
          return new string(res, 0, j);
      }
      

      即使 '\n\r' 实际上并没有在基本平台上使用,翻译表对我也很有吸引力。谁会使用两种类型的换行符来指示 2 个换行符? 如果你想知道这一点,那么你需要先看看 \n 和 \r 是否在同一个文档中单独使用。

      【讨论】:

      猜你喜欢
      • 2011-06-20
      • 2012-05-21
      • 2019-07-08
      • 2010-11-16
      • 2020-12-13
      • 2012-05-22
      • 2016-05-17
      • 1970-01-01
      相关资源
      最近更新 更多