211

C# では、文字列値を文字列リテラルに変換することはできますか? コードで見る方法は? タブや改行などをエスケープシーケンスに置き換えたいと思います。

このコードの場合:

Console.WriteLine(someString);

生成:

Hello
World!

このコードが欲しい:

Console.WriteLine(ToLiteral(someString));

生産する:

\tHello\r\n\tWorld!\r\n
4

16 に答える 16

197

私はこれを見つけました:

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

このコード:

var input = "\tHello\r\n\tWorld!";
Console.WriteLine(input);
Console.WriteLine(ToLiteral(input));

プロデュース:

    Hello
    World!
"\tHello\r\n\tWorld!"
于 2008-11-27T23:40:44.613 に答える
47

Regex.Escape(String)を使用します。

Regex.Escape は、最小限の文字セット (、*、+、?、|、{、[、(,)、^、$、.、#、および空白) をエスケープ コードに置き換えることでエスケープします。

于 2013-01-16T11:31:19.350 に答える
27

これは、Unicode および ASCII の印刷不能文字のエスケープを含む、完全に機能する実装です。Hallgrim's answer のような「+」記号は挿入しません。

static string ToLiteral(string input) {
    StringBuilder literal = new StringBuilder(input.Length + 2);
    literal.Append("\"");
    foreach (var c in input) {
        switch (c) {
            case '\"': literal.Append("\\\""); break;
            case '\\': literal.Append(@"\\"); break;
            case '\0': literal.Append(@"\0"); break;
            case '\a': literal.Append(@"\a"); break;
            case '\b': literal.Append(@"\b"); break;
            case '\f': literal.Append(@"\f"); break;
            case '\n': literal.Append(@"\n"); break;
            case '\r': literal.Append(@"\r"); break;
            case '\t': literal.Append(@"\t"); break;
            case '\v': literal.Append(@"\v"); break;
            default:
                // ASCII printable character
                if (c >= 0x20 && c <= 0x7e) {
                    literal.Append(c);
                // As UTF16 escaped character
                } else {
                    literal.Append(@"\u");
                    literal.Append(((int)c).ToString("x4"));
                }
                break;
        }
    }
    literal.Append("\"");
    return literal.ToString();
}

これにより、すべての Unicode 文字もエスケープされることに注意してください。環境がそれらをサポートしている場合は、その部分を変更して、制御文字のみをエスケープできます。

// UTF16 control characters
} else if (Char.GetUnicodeCategory(c) == UnicodeCategory.Control) {
    literal.Append(@"\u");
    literal.Append(((int)c).ToString("x4"));
} else {
    literal.Append(c);
}
于 2012-12-30T02:18:37.083 に答える
27

strings およびcharsのすべてのエスケープ シーケンスを含む、より構造化されたアプローチは次のとおりです。

Unicode 文字をそのリテラルに相当する文字に置き換えません。卵も調理しません。

public class ReplaceString
{
    static readonly IDictionary<string, string> m_replaceDict
        = new Dictionary<string, string>();

    const string ms_regexEscapes = @"[\a\b\f\n\r\t\v\\""]";

    public static string StringLiteral(string i_string)
    {
        return Regex.Replace(i_string, ms_regexEscapes, match);
    }

    public static string CharLiteral(char c)
    {
        return c == '\'' ? @"'\''" : string.Format("'{0}'", c);
    }

    private static string match(Match m)
    {
        string match = m.ToString();
        if (m_replaceDict.ContainsKey(match))
        {
            return m_replaceDict[match];
        }

        throw new NotSupportedException();
    }

    static ReplaceString()
    {
        m_replaceDict.Add("\a", @"\a");
        m_replaceDict.Add("\b", @"\b");
        m_replaceDict.Add("\f", @"\f");
        m_replaceDict.Add("\n", @"\n");
        m_replaceDict.Add("\r", @"\r");
        m_replaceDict.Add("\t", @"\t");
        m_replaceDict.Add("\v", @"\v");

        m_replaceDict.Add("\\", @"\\");
        m_replaceDict.Add("\0", @"\0");

        //The SO parser gets fooled by the verbatim version
        //of the string to replace - @"\"""
        //so use the 'regular' version
        m_replaceDict.Add("\"", "\\\"");
    }

    static void Main(string[] args){

        string s = "here's a \"\n\tstring\" to test";
        Console.WriteLine(ReplaceString.StringLiteral(s));
        Console.WriteLine(ReplaceString.CharLiteral('c'));
        Console.WriteLine(ReplaceString.CharLiteral('\''));

    }
}
于 2008-11-27T12:49:38.440 に答える
21

試す:

var t = HttpUtility.JavaScriptStringEncode(s);
于 2012-03-02T11:04:00.363 に答える
19

ホールグリムの答えは素晴らしいですが、「+」、改行、インデントの追加は機能を壊していました。それを回避する簡単な方法は次のとおりです。

private static string ToLiteral(string input)
{
    using (var writer = new StringWriter())
    {
        using (var provider = CodeDomProvider.CreateProvider("CSharp"))
        {
            provider.GenerateCodeFromExpression(new CodePrimitiveExpression(input), writer, new CodeGeneratorOptions {IndentString = "\t"});
            var literal = writer.ToString();
            literal = literal.Replace(string.Format("\" +{0}\t\"", Environment.NewLine), "");
            return literal;
        }
    }
}
于 2013-02-06T00:41:58.087 に答える
19
public static class StringHelpers
{
    private static Dictionary<string, string> escapeMapping = new Dictionary<string, string>()
    {
        {"\"", @"\\\"""},
        {"\\\\", @"\\"},
        {"\a", @"\a"},
        {"\b", @"\b"},
        {"\f", @"\f"},
        {"\n", @"\n"},
        {"\r", @"\r"},
        {"\t", @"\t"},
        {"\v", @"\v"},
        {"\0", @"\0"},
    };

    private static Regex escapeRegex = new Regex(string.Join("|", escapeMapping.Keys.ToArray()));

    public static string Escape(this string s)
    {
        return escapeRegex.Replace(s, EscapeMatchEval);
    }

    private static string EscapeMatchEval(Match m)
    {
        if (escapeMapping.ContainsKey(m.Value))
        {
            return escapeMapping[m.Value];
        }
        return escapeMapping[Regex.Escape(m.Value)];
    }
}
于 2008-11-27T16:00:09.270 に答える
19

NuGetのRoslynMicrosoft.CodeAnalysis.CSharpパッケージには、このためのメソッドがあります。

private static string ToLiteral(string valueTextForCompiler)
{
    return Microsoft.CodeAnalysis.CSharp.SymbolDisplay.FormatLiteral(valueTextForCompiler, false);
}

明らかに、これは元の質問の時点では存在しませんでしたが、Google検索からここにたどり着いた人々を助けるかもしれません.

于 2019-11-12T19:50:58.523 に答える
10

これは、 Smilediver の回答を少し改善したものです。すべての非 ASCII 文字をエスケープするわけではありませんが、実際に必要なのはこれらだけです。

using System;
using System.Globalization;
using System.Text;

public static class CodeHelper
{
    public static string ToLiteral(this string input)
    {
        var literal = new StringBuilder(input.Length + 2);
        literal.Append("\"");
        foreach (var c in input)
        {
            switch (c)
            {
                case '\'': literal.Append(@"\'"); break;
                case '\"': literal.Append("\\\""); break;
                case '\\': literal.Append(@"\\"); break;
                case '\0': literal.Append(@"\0"); break;
                case '\a': literal.Append(@"\a"); break;
                case '\b': literal.Append(@"\b"); break;
                case '\f': literal.Append(@"\f"); break;
                case '\n': literal.Append(@"\n"); break;
                case '\r': literal.Append(@"\r"); break;
                case '\t': literal.Append(@"\t"); break;
                case '\v': literal.Append(@"\v"); break;
                default:
                    if (Char.GetUnicodeCategory(c) != UnicodeCategory.Control)
                    {
                        literal.Append(c);
                    }
                    else
                    {
                        literal.Append(@"\u");
                        literal.Append(((ushort)c).ToString("x4"));
                    }
                    break;
            }
        }
        literal.Append("\"");
        return literal.ToString();
    }
}
于 2013-01-24T13:17:01.793 に答える
8

興味深い質問です。

より良い方法が見つからない場合は、いつでも交換できます。それを選択している場合は、このC# Escape Sequence List
を使用できます。

  • \' - 文字リテラルに必要な一重引用符
  • \" - 文字列リテラルに必要な二重引用符
  • \ - バックスラッシュ
  • \0 - Unicode 文字 0
  • \a - アラート (文字 7)
  • \b - バックスペース (文字 8)
  • \f - フォーム フィード (文字 12)
  • \n - 改行 (文字 10)
  • \r - キャリッジ リターン (文字 13)
  • \t - 水平タブ (文字 9)
  • \v - 垂直引用符 (文字 11)
  • \uxxxx - 16 進値 xxxx を持つ文字の Unicode エスケープ シーケンス
  • \xn[n][n][n] - 16 進値 nnnn を持つ文字の Unicode エスケープ シーケンス (\uxxxx の可変長バージョン)
  • \Uxxxxxxxx - 16 進値 xxxxxxxx を持つ文字の Unicode エスケープ シーケンス (サロゲートの生成用)

このリストは、C# のよく寄せられる質問の 「利用可能な文字エスケープ シーケンスは何ですか?」にあります。

于 2008-11-27T12:48:11.593 に答える
0

独自の実装を提出します。これは値を処理し、配列ルックアップ テーブルの使用、手動の 16 進変換、およびステートメントnullの回避によりパフォーマンスが向上するはずです。switch

using System;
using System.Text;
using System.Linq;

public static class StringLiteralEncoding {
  private static readonly char[] HEX_DIGIT_LOWER = "0123456789abcdef".ToCharArray();
  private static readonly char[] LITERALENCODE_ESCAPE_CHARS;

  static StringLiteralEncoding() {
    // Per http://msdn.microsoft.com/en-us/library/h21280bw.aspx
    var escapes = new string[] { "\aa", "\bb", "\ff", "\nn", "\rr", "\tt", "\vv", "\"\"", "\\\\", "??", "\00" };
    LITERALENCODE_ESCAPE_CHARS = new char[escapes.Max(e => e[0]) + 1];
    foreach(var escape in escapes)
      LITERALENCODE_ESCAPE_CHARS[escape[0]] = escape[1];
  }

  /// <summary>
  /// Convert the string to the equivalent C# string literal, enclosing the string in double quotes and inserting
  /// escape sequences as necessary.
  /// </summary>
  /// <param name="s">The string to be converted to a C# string literal.</param>
  /// <returns><paramref name="s"/> represented as a C# string literal.</returns>
  public static string Encode(string s) {
    if(null == s) return "null";

    var sb = new StringBuilder(s.Length + 2).Append('"');
    for(var rp = 0; rp < s.Length; rp++) {
      var c = s[rp];
      if(c < LITERALENCODE_ESCAPE_CHARS.Length && '\0' != LITERALENCODE_ESCAPE_CHARS[c])
        sb.Append('\\').Append(LITERALENCODE_ESCAPE_CHARS[c]);
      else if('~' >= c && c >= ' ')
        sb.Append(c);
      else
        sb.Append(@"\x")
          .Append(HEX_DIGIT_LOWER[c >> 12 & 0x0F])
          .Append(HEX_DIGIT_LOWER[c >>  8 & 0x0F])
          .Append(HEX_DIGIT_LOWER[c >>  4 & 0x0F])
          .Append(HEX_DIGIT_LOWER[c       & 0x0F]);
    }

    return sb.Append('"').ToString();
  }
}
于 2013-06-03T22:15:09.333 に答える
-9

コード:

string someString1 = "\tHello\r\n\tWorld!\r\n";
string someString2 = @"\tHello\r\n\tWorld!\r\n";

Console.WriteLine(someString1);
Console.WriteLine(someString2);

出力:

    Hello
    World!

\tHello\r\n\tWorld!\r\n
于 2008-11-27T14:36:44.667 に答える