无法在字符串中搜索换行符

Unable to search for newline character in string

在 C# 中,我正在寻找字符串中字符串的索引 - 特别是换行符 (\n) 所在的索引。

给定一个带有 Windows 换行符 (\r\n) 的字符串:

如果我寻找 "\n",它会给我 -1。如果我查找 "\r\n",我会得到一个结果。如果我寻找 '\n' 作为字符,我会得到一个结果。

给定一个带有 Unix 换行符的字符串 (\n),我得到一个结果。

string s = "hello\r\nworld";

Console.WriteLine(@"\r\n index: " + s.IndexOf("\r\n")); // 5
Console.WriteLine(@"\n index as string: " + s.IndexOf("\n")); // -1
Console.WriteLine(@"\n index as char: " + s.IndexOf('\n')); // 6


s = "hello\nworld";

Console.WriteLine(@"\n index as string: " + s.IndexOf("\n")); // 5
Console.WriteLine(@"\n index as char: " + s.IndexOf('\n')); // 5

我知道换行符是两个字符,如果我使用 StreamReader 或 File.ReadAllLines 或类似的东西,那么它会自动处理,我会丢失它们。

我认为 \n 本身就是一个有效的字符串,而 \r\n 虽然特殊,但仍然表示字符串中两个独立且不同的字符。但这告诉我事实并非如此。

我可以对字符而不是字符串执行 IndexOf('\n' 而不是 "\n"),但我真的很想知道为什么会这样,以便我可以计划一下。

编辑

仅供参考:刚刚发现将字符串转换为 Span 会给出正确的结果。不确定其中涉及的开销,所以我不知道这与 Ordinal 解决方案相比如何 - 我猜 Ordinal 是更好的解决方案:

Console.WriteLine(@"\n index as string Ordinal: " 
    + s.IndexOf("\n", StringComparison.Ordinal)); // 6

Console.WriteLine(@"\n index as Span: "
    + s.AsSpan().IndexOf("\n".AsSpan())); // 6

Console.WriteLine(@"\n index as string with s.AsSpan(): " 
    + s.AsSpan().IndexOf("\n")); // 6

.Net 5.0 中的 Windows 全球化库发生了变化。在以前的版本中,NLS 在 Windows 上使用,在 Unix 上使用 ICU。 .Net 5 在两者上都使用了 ICU 以使跨平台开发保持一致,但代价是令 Windows 开发人员感到惊讶 (sigh)。由于此更改,您必须传递 StringComparison.Ordinal 才能在字符串中找到换行符。

请注意,这也可能取决于 Windows 的版本(双 sigh),因为 Windows 2019 年 5 月 10 日包括 ICU 库和更早版本否则将导致 .Net 5 退回到 NLS。

请参阅 Microsoft 的 this articleThis article 包含有关受影响的 API 的更多详细信息。

您可以在脚本中使用 System.Environment.NewLine,这是换行符的条件 属性,具体取决于操作系统。检查 here.

在 Windows 上:"\r\n"
在 unix 平台上:"\n".

using System;
string s = "hello" + Environment.NewLine + "world";