如何在字符串中写入单个反斜杠 (\)?

How do I write a single backslash (\) in a string?

我正在尝试检测字符串中的不可打印字符('\n'、'\r' 等)并在它们之前插入一个反斜杠。因此,例如,如果我有一个字符串“Hello\nWorld”,我希望它是“Hello\\nWorld”。我有一个应该执行此操作的代码示例,但它插入了一个双反斜杠 ('\\'),所以结果是“Hello\\\nWorld”。有没有办法在字符串中插入单个反斜杠?

expression = Regex.Replace(expression, @"\p{Cc}", m =>
            {
                int code = m.Value[0];

                return code < 32
                            ? @"\" + $"{Convert.ToChar(code)}"
                            : Convert.ToChar(code).ToString();
            });

如果您不想要 TLDR,请跳到最后..

当你这样写的时候:

var s = "Hello\nWorld";

编译器将 \n 转换为换行符,为您提供:

 Hello
 World

当你这样写的时候:

var s = "Hello\nWorld";

编译器将 \ 转换为单个反斜杠字符,为您提供:

Hello\nWorld

当你写这个逐字字符串:

var s = @"Hello\nWorld";

前导 @ 关闭任何斜杠字符的编译器转换,因此您得到:

Hello\nWorld

当您在调试器工具提示或 autos/locals window 中查看字符串时,它会显示 non-verbatim 字符串。即它向您显示 您必须粘贴到源代码中的字符串才能获得您想要输出的字符串:

如果您想查看字符串的实际显示方式,例如,写入文件,用记事本打开,点击字符串值旁边的放大镜


如果您通过写入工具提示或自动 window 来编辑值,并且通过在其前面添加 @:

来写入逐字字符串

请记住,当调试器工具提示接下来向您显示它时,它将恢复为 non-verbatim 字符串:

这里现在有 4 个斜杠,因为我们通过制作一个具有 2 个斜杠的逐字字符串和 2 real-slashes 加倍到 4 sourcecode-slashes 来编辑它。这样一来,如果您将它作为 non-verbatim 字符串粘贴到代码中,编译器会在编译时将这 4 个斜杠转换为 2 个斜杠..


希望您现在对“编译器斜杠”感到失望。这是接下来要加入的事情..

正则表达式引擎也是一种编译器,它也进行这些转换。

当你有一个“单词字符”的正则表达式时:

\w

您需要先通过 C# 编译器转换 - C# 编译器转换发生在编译时,但 Regex 引擎转换发生在运行时

如果你只写这个:

var r = new Regex("\w");

编译器将尝试转换 \w 并在其上阻塞,因为它没有 \w 的斜杠转换,就像 \newline 或 [=35] =]ab

这意味着要让正则表达式引擎看到 \w 您需要执行以下任一操作:

var r = new Regex("\w");
var r = new Regex(@"\w");

C# 编译器将这两者变为 \w,因此这就是 Regex 引擎所看到的


一些 slashed-characters 对编译器和正则表达式引擎都有意义

正则表达式引擎可以理解 \n(2 个字符:字面意思是斜杠后跟 n)或换行符 (1 个字符,ascii [中的第 10 个字符) =168=]) 所以要让 Regex 寻找换行符,您可以:

var r = new Regex("\n");    //compiler converts to newline char
var r = new Regex(@"
");                         //source code literally contains a newline char
var r = new Regex(@"\n");   //compiler ignores, regex engine interprets \n as newline
var r = new Regex("\n");   //compiler converts \ to \, regex engine interprets \n as newline

所以请记住这两个步骤的转换。使用@strings 关闭编译器转换可能是最简单的方法,然后当您在源代码中编写斜线时,您的斜线会通过正则表达式引擎。如果您需要通过正则表达式获得 ",请编写 ""

var r = new Regex(@"He said ""I don't know"" to me");

另请注意,在最近的 visual studio 中,正则表达式中的字符串会针对正则表达式引擎所看到的内容获得额外有用的语法高亮显示:


既然我们已经解决了所有这些问题,并且您理解正在进行的多级转换,希望您能够理解您无法使用 Regex 完成您所要求的事情。没有任何概念认为以下字符串:

Hello
World

其中,在源代码中可以是:

var s1 = "Hello\nWorld";
var s2 = @"Hello
World";

可以“在换行符前面放置一个斜杠”并作为 \n 弹出,因为它不是字符串中的 n。单词之间有一些空格的字符串“Hello World”根本不包含 n,任何地方

编译器基本上完成了:

code = code.Replace(@"\n", @"
");                                 //change slash-n to newline char 10

你不能用以下方式反转它:

var x = code.IndexOf("
");                                 //find newline char
code = code.Insert(x, @"\");        //insert slash before newline

一串“slash-newline”不是“slash-n”

唯一的回归是:

code = code.Replace(@"
", @"\n");                          //replace newline char with slash-n

您将找到的所有内容都没有斜杠代码。我猜你可以用你目前的方法做的唯一一件事是:

expression = Regex.Replace(expression, @"\p{Cc}", m => $@"\u{(int)m.Value[0]:x4}");

这将需要一些字符串,例如:

Hello
World

然后变成

Hello\u000aWorld

如果您希望它成为 \n,您必须为其(以及所有其他 slash-whatevers)编写代码,特别是通过大量 table 替换:

Table 由 https://www.tutorialspoint.com/csharp/csharp_character_escapes.htm

提供