规范化C#中的换行符

我有一个数据流可能包含\ 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 

我相信这会做你需要的:

 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 \ n转换为\ r \ n,但我不会调用该规范化。

一个正则表达式会帮助..可以做一些像这样的事情..

(\ 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 

我和Regie的Jamie Zawinski在一起:

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

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

  • 步骤1

    用\ n替换\ r \ n

    将\ n \ n替换为\ n(如果你真的想要这个,有些海报似乎没有想到)

    用\ n替换\ r

  • 步骤2用Environment.NewLine或\ r \ n或其他替换\ n。

你觉得太复杂了。 忽略每个\ r并将每个\ n转换为\ r \ n。

在Pseudo-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 \ n单独没有行终结符所以我怀疑你真的想要扩展\ r到\ r \ n。

我同意正则表达式是答案,但是,其他人都没有提到Unicode行分隔符。 那些(及其与\ n的变体)应该包括在内。

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

因此,搜索直接在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 \ n是否在同一文档中单独使用。

标准化中断,使它们都是\r\n

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