¿Puedo convertir un valor de cadena C # en un literal de cadena escapado?

En C #, ¿puedo convertir un valor de cadena en un literal de cadena, de la misma forma que lo vería en el código? Me gustaría reemplazar tabs, líneas nuevas, etc. con sus secuencias de escape.

Si este código:

Console.WriteLine(someString); 

produce:

 Hello World! 

Quiero este código:

 Console.WriteLine(ToLiteral(someString)); 

para producir:

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

Encontré esto:

 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(); } } } 

Este código:

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

Produce:

  Hello World! "\tHello\r\n\tWorld!" 

¿Qué pasa con Regex.Escape (String) ?

Regex.Escape escapa de un conjunto mínimo de caracteres (\, *, +,?, |, {, [, (,), ^, $,., # Y espacio en blanco) reemplazándolos con sus códigos de escape.

EDITAR: Un enfoque más estructurado, que incluye todas las secuencias de escape para string s y char s.
No reemplaza los caracteres Unicode con su equivalente literal. Tampoco cocina los huevos.

 public class ReplaceString { static readonly IDictionary m_replaceDict = new Dictionary(); 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('\'')); } } 
 public static class StringHelpers { private static Dictionary escapeMapping = new Dictionary() { {"\"", @"\\\"""}, {"\\\\", @"\\"}, {"\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)]; } } 

tratar:

 var t = HttpUtility.JavaScriptStringEncode(s); 

Implementación totalmente operativa, incluido el escape de caracteres no imprimibles Unicode y ASCII. No inserta signos “+” como la respuesta de Hallgrim .

  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 '\\': 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(); } 

La respuesta de Hallgrim es excelente, pero las adiciones “+”, nueva línea y sangría estaban rompiendo la funcionalidad para mí. Una manera fácil de resolverlo es:

 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; } } } 

Interesante pregunta.

Si no puede encontrar un método mejor, siempre puede reemplazarlo.
En caso de que lo opte, puede usar esta lista de secuencias de escape de C # :

  • \ ‘- comilla simple, necesaria para literales de caracteres
  • \ “- comillas dobles, necesarias para literales de cadenas
  • \ – barra invertida
  • \ 0 – carácter Unicode 0
  • \ a – Alerta (carácter 7)
  • \ b – Retroceso (carácter 8)
  • \ f – Alimentación del formulario (carácter 12)
  • \ n – Nueva línea (carácter 10)
  • \ r – Retorno de carro (carácter 13)
  • \ t – Pestaña horizontal (carácter 9)
  • \ v – Cita vertical (carácter 11)
  • \ uxxxx – Secuencia de escape Unicode para el carácter con valor hexadecimal xxxx
  • \ xn [n] [n] [n] – Secuencia de escape Unicode para caracteres con valor hexadecimal nnnn (versión de longitud variable de \ uxxxx)
  • \ Uxxxxxxxx – Secuencia de escape Unicode para caracteres con valor hexadecimal xxxxxxxx (para generar sustitutos)

Esta lista se transpuso a esta respuesta ya que el enlace original dejó de estar disponible:
Listado de las secuencias de escape de C #

Aún se puede acceder al artículo completo a través de Wayback Machine .

Aquí hay una pequeña mejora para la respuesta de Smilediver, no escapará a todos los caracteres no ASCII, pero solo estos son realmente necesarios.

 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(); } } 
 public static class StringEscape { static char[] toEscape = "\0\x1\x2\x3\x4\x5\x6\a\b\t\n\v\f\r\xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\"\\".ToCharArray(); static string[] literals = @"\0,\x0001,\x0002,\x0003,\x0004,\x0005,\x0006,\a,\b,\t,\n,\v,\f,\r,\x000e,\x000f,\x0010,\x0011,\x0012,\x0013,\x0014,\x0015,\x0016,\x0017,\x0018,\x0019,\x001a,\x001b,\x001c,\x001d,\x001e,\x001f".Split(new char[] { ',' }); public static string Escape(this string input) { int i = input.IndexOfAny(toEscape); if (i < 0) return input; var sb = new System.Text.StringBuilder(input.Length + 5); int j = 0; do { sb.Append(input, j, i - j); var c = input[i]; if (c < 0x20) sb.Append(literals[c]); else sb.Append(@"\").Append(c); } while ((i = input.IndexOfAny(toEscape, j = ++i)) > 0); return sb.Append(input, j, input.Length - j).ToString(); } } 

Mi bash de agregar ToVerbatim a la respuesta aceptada de Hallgrim arriba:

 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; } } } private static string ToVerbatim( string input ) { string literal = ToLiteral( input ); string verbatim = "@" + literal.Replace( @"\r\n", Environment.NewLine ); return verbatim; } 

Presento mi propia implementación, que maneja valores null y debería ser más eficaz a la hora de utilizar tablas de búsqueda de matriz, conversión hexadecimal manual y evitar declaraciones de 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]; } ///  /// Convert the string to the equivalent C# string literal, enclosing the string in double quotes and inserting /// escape sequences as necessary. ///  /// The string to be converted to a C# string literal. ///  represented as a C# string literal. 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(); } } 

Código:

 string someString1 = "\tHello\r\n\tWorld!\r\n"; string someString2 = @"\tHello\r\n\tWorld!\r\n"; Console.WriteLine(someString1); Console.WriteLine(someString2); 

Salida:

  Hello World! \tHello\r\n\tWorld!\r\n 

¿Es esto lo que quieres?