如何正确转义字符串

6
我有一个字符串要发送给外部打印函数。
我需要用反斜杠填充字符串,以便正确打印。
具体来说,我需要一个方法,它将接受此示例输入:
This is a string\nwith a line break\ta tab\rand a carriage return. 并输出:
This is a string\\nwith a line break\\ta tab\\rand a carriage return. 我需要暴力替换每个可能的转义字符为其反斜杠等效形式吗?
尝试过:
s.Replace("\\","\\\\") 不起作用,因为它正在寻找反斜杠字面量。 s.Replace("\n","\\n") 显然可行,但我想要的是一种通用方法。
编辑: 请不要建议暴力方法,我知道可以实现这样的方法。我的问题是是否存在更通用的方法。

您的输入不清楚 - 您的意思是要将“带有换行符的字符串”转换为“带有反斜杠后跟n的字符串”吗? - Jon Skeet
@Jon 是的,没错。我需要准备好我的字符串以进行双重转义。 - Rotem
3
C# 字面字符串 "This is a string\nwith a line break" 中没有反斜杠符号,确实有一个换行符号,但没有反斜杠。在该字符串中没有需要进行双重转义的内容。 - prprcupofcoffee
@David 或许“双重转义”这个术语不太准确,但所需的输出结果仍然是正确的。 - Rotem
1
你可以使用 char.IsControl(char c) 来检测字符是否为控制字符,但我不确定如何将其转换为可打印字符。 - JG in SD
显示剩余2条评论
3个回答

12
private static string EscapeLiterals(string input)
{
    using (var writer = new StringWriter())
    {
        using (var provider = CodeDomProvider.CreateProvider("CSharp"))
        {
            provider.GenerateCodeFromExpression(new CodePrimitiveExpression(input), writer, null);
            return writer.ToString();
        }
    }
}

将输入的"\tHello\r\n\tLiterals!"转换为"\\tHello\\r\\n\\tLiterals!"

适用于任何输入 - 它将为您获取任何内容的转义序列。


1
太棒了,谢谢!还值得一提的是,这些类存在于 System.CodeDomSystem.CodeDom.Compiler 命名空间中。 - Rotem
1
不错,但要注意对于较长的字符串,这将插入“+”运算符、换行和缩进。我找不到关闭它的方法。 - Timwi

3
这是我用来处理此问题的函数。我已经在生产代码中使用了多年,它似乎能够处理各种边角情况。
/// <summary>
/// Escapes all characters in this string whose code is less than 32 using C/C#-compatible backslash escapes.
/// </summary>
public static string CLiteralEscape(this string value)
{
    if (value == null)
        throw new ArgumentNullException("value");

    var result = new StringBuilder(value.Length + value.Length / 2);

    for (int i = 0; i < value.Length; i++)
    {
        char c = value[i];
        switch (c)
        {
            case '\0': result.Append(@"\0"); break;
            case '\a': result.Append(@"\a"); break;
            case '\b': result.Append(@"\b"); break;
            case '\t': result.Append(@"\t"); break;
            case '\n': result.Append(@"\n"); break;
            case '\v': result.Append(@"\v"); break;
            case '\f': result.Append(@"\f"); break;
            case '\r': result.Append(@"\r"); break;
            case '\\': result.Append(@"\\"); break;
            case '"': result.Append(@"\"""); break;
            default:
                if (c >= ' ')
                    result.Append(c);
                else // the character is in the 0..31 range
                    result.AppendFormat(@"\x{0:X2}", (int) c);
                break;
        }
    }

    return result.ToString();
}

这就是我所说的问题中所提到的暴力方法 - 尽管因列出单元测试用例而获得了赞 :P - Markus

0

您可以使用多个替换来强制将空格替换为可读的控制字符:

s = s.Replace("\n", "\\n").Replace("\r", "\\r").Replace("\t", "\\t");

然而,你不能像你想象的那样简单地加倍反斜杠,因为字符已经在内存中转换为其二进制值。因此,你需要手动替换每个字符。


1
我特别说明了我知道这个方法可行,而且我正在寻找一种处理所有控制字符的方法。 - Rotem
在我的第一个答案版本中,我犯了一个错误。 - rekire
是的,谢谢你,但这是一种暴力破解方法,我特别说了我不想要它。 - Rotem
关于 brute force 的问题稍后解决,但我看没有其他的解决办法。有一系列非常有限的空白字符可以像您想要的那样进行转义 - rekire

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接