0

我正在尝试检测字符串中的不可打印字符('\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();
            });
4

1 回答 1

3

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

当你写这个:

var s = "Hello\nWorld";

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

 Hello
 World

当你写这个:

var s = "Hello\\nWorld";

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

Hello\nWorld

当您编写此逐字字符串时:

var s = @"Hello\nWorld";

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

Hello\nWorld

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

在此处输入图像描述

如果您想查看如果您将字符串写入文件并在记事本中打开它时实际显示的字符串,请单击字符串值旁边的放大镜

在此处输入图像描述


如果您通过写入工具提示或自动窗口来编辑该值,并且您通过在其前面添加一个逐字字符串@

在此处输入图像描述

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

在此处输入图像描述

这里现在有 4 个斜杠,因为我们通过创建一个包含 2 个斜杠的逐字字符串来编辑它,并且 2 个实斜杠加倍到 4 个源代码斜杠。这样一来,如果您将其作为非逐字字符串粘贴到代码中,编译器会在编译时将这 4 个斜杠转换为 2 个斜杠。


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

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

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

\w

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

如果你只是这样写:

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

编译器将尝试转换它\w并阻塞它,因为它没有\w\newline 或\tab那样的斜线转换

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

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

这两者\w都由 C# 编译器生成,所以这就是 Regex 引擎所看到的


一些斜线字符对编译器和正则表达式引擎都有意义

正则表达式引擎可以理解\n(2 个字符:字面上是一个斜线,后跟一个n)或换行符 (1 个字符,ascii 表中的字符 10),因此要让正则表达式寻找换行符,您可以:

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你必须专门通过有一个大的替换表来为它(以及所有其他斜杠)编码:

在此处输入图像描述

表格由https://www.tutorialspoint.com/csharp/csharp_character_escapes.htm提供

于 2022-02-22T09:54:14.870 回答