提问人:s_v 提问时间:7/11/2023 最后编辑:s_v 更新时间:7/11/2023 访问量:243
在 C 中处理转义序列#
Handle escape sequences in C#
问:
我有一个将 rawText 作为字符串输入的 C# 端点。
输入是在将 a 转换为使用第三方库后发送的,发送的输入格式如下,例如 -file
string
aspose
{rawText = "\u0007\u0007\r\r\r\r\r\u0007Random Name\rRandom Address; Overland Park, KS 12345; Cell: 000-000-0000 Email: [email protected]"}
我知道字符串是用 C# 编码的 UTF16,所以当它到达端点时,它会转换为 -
requestobj.RawText = "\a\a\r\r\r\r\r\aRandom Name\r10504 Random Address; Overland Park, KS 12345; Cell: 000-000-0000 Email: [email protected]"
我的推理是否正确,这是由于 C# 字符串是 utf16 编码的?以及删除字符串开头的最佳方法是什么。我正在将此文本传递给另一个第三方 api,该 api 不会返回带有此预置额外文本的正确结果。\a\a\r\r\r\r\r\a
我尝试在下面使用,但我想要一个更通用的解决方案来处理等所有可能性。\n\r\a
var newText = Regex.Replace(inputValue, @"\\a", "");
inputValue = inputValue.Replace(@"\a", "").Replace(@"\r", "");
答:
这些是转义序列,而不是 UTF8 编码。编码是指如何将字符转换为字节。转义序列用于输入在源代码中难以键入或不可见的字符。调试器也使用它们来显示此类字符。在问题的情况下,没有任何转换。相同的 BELL 字符 (0x07) 可以表示为 both 或 。调试器选择了较短的版本。\a
\u0007
要在开始时仅替换这 3 个字符,您可以使用此正则表达式 。为了避免在正则表达式中对转义序列进行双引号,可以使用不转换为转义字符的逐字字符串。@"^[\r\n\a]+"
\
var input="\a\a\r\r\r\r\r\aRandom Name\r10504 Random Address; Overland Park, KS 12345; Cell: 000-000-0000 Email: [email protected]";
var pattern=@"^[\r\n\a]+";
var newText=Regex.Replace(input,pattern,"");
这会产生
Random Name 10504 Random Address; Overland Park, KS 12345; Cell: 000-000-0000 Email: [email protected]
要删除任何位置的字符,请删除起始锚点。^
也可以替换所有控制字符。对于带有 的控制字符,有一个特定的 Unicode 类别。 是控制字符类别的简写。\p{Cc}
Cc
var pattern=@"\p{Cc}+";
var newText=Regex.Replace(input,pattern,"");
正如文档所解释的,此类别与任何
控制代码字符,Unicode 值为 U+007F 或范围为 U+0000 到 U+001F 或 U+0080 到 U+009F。由 Unicode 名称“Cc”(其他、控件)表示。
评论
正如 Panagiotis 所指出的,字符串中转义码的表示只是视觉表示,不会改变字符串的含义或编码。是的,C#(以及一般的 .NET)使用 Unicode/UTF-16 对内存中的字符串进行编码,但这与您的问题无关,在大多数情况下也不重要。
撇开这一点不谈,你的主要问题似乎是这样的:
在字符串开头删除\a\a\r\r\r\r\r\a的最佳方法是什么。
与大多数此类问题一样,有很多方法可以解决这个问题。正则表达式(正如 Panagiotis 所建议的)当然可以完成这项工作,但它们可能很挑剔,并且通常比更直接的选项慢。有时正则表达式最适合特定问题,但这不一定是其中之一。我不认为您正在寻找最快的解决方案......但探索各种选择并没有什么坏处。
所以这里有一些想法。
如果您希望从字符串的开头删除少量已知字符,那么可以使用字符串方法: .具体来说,接受一组要删除的字符的版本:TrimStart()
string cleanText = inputText.TrimLeft('\a', '\r', '\n');
对于少数已知字符来说,这很好。但是,如果您希望从字符串的开头删除任何控制字符,则可以对它们进行计数并从字符串中跳过许多字符:
// Count control characters at the start of the string:
int count = 0;
for (; count < inputText.Length && Char.IsControl(inputText, count); count++)
{ }
// This monster is safe:
string cleanText =
count == 0 ? inputText :
count >= inputText.Length ? string.Empty :
inputText[count..];
这恰好是完成该特定工作的最快方法之一,但它不是最漂亮的。除非你经常这样做,否则你可能不会每次都错过额外的几毫秒。
由于性能不是一个关键问题,让我向您介绍一个最慢的选项:LINQ。
string cleanText = new string(inputText.SkipWhile(c => char.IsControl(c)).ToArray());
虽然坦率地说,它的性能很糟糕,但它比高性能版本更具可读性。 在满足条件时跳过项目,其余字符被收集到一个数组中并用于创建新字符串。它很漂亮,但很慢。就像我的猫一样。SkipWhile()
评论
\u0007
\a