无法在字符串中搜索换行符
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 article。
This article 包含有关受影响的 API 的更多详细信息。
您可以在脚本中使用 System.Environment.NewLine
,这是换行符的条件 属性,具体取决于操作系统。检查 here.
在 Windows 上:"\r\n"
。
在 unix 平台上:"\n"
.
using System;
string s = "hello" + Environment.NewLine + "world";
在 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 article。 This article 包含有关受影响的 API 的更多详细信息。
您可以在脚本中使用 System.Environment.NewLine
,这是换行符的条件 属性,具体取决于操作系统。检查 here.
在 Windows 上:"\r\n"
。
在 unix 平台上:"\n"
.
using System;
string s = "hello" + Environment.NewLine + "world";