답변:
나는 이것을 찾았다:
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!"
@"..."
리터럴 ( ) 리터럴을 출력하는 방법이 있습니까?
무엇에 대한 Regex.Escape (문자열) ?
Regex.Escape는 이스케이프 코드로 대체하여 최소 문자 세트 (\, *, +,?, |, {, [, (,), ^, $,., # 및 공백)를 이스케이프합니다.
Hello World?
으로 Hello World\?
, 그러나 그것은 잘못된 문자열 리터럴입니다.
편집 : string
s 및 char
s에 대한 모든 이스케이프 시퀀스를 포함하여보다 체계적인 접근 방식 .
유니 코드 문자를 해당 문자로 대체하지 않습니다. 계란도 요리하지 않습니다.
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('\''));
}
}
@"[\a\b\f\n\r\t\v\\""/]"
하고에 추가 m_replaceDict.Add("/", @"\/");
했습니다 JSON
.
시험:
var t = HttpUtility.JavaScriptStringEncode(s);
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)];
}
}
유니 코드 및 ASCII 인쇄 할 수없는 문자의 이스케이프 처리를 포함한 완전한 작업 구현. 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();
}
Char.GetUnicodeCategory(c) == UnicodeCategory.Control
이스케이프를 피할 것인지 결정 해야합니다. 그렇지 않으면 ASCII를 사용하지 않는 사람들은 행복하지 않습니다.
input = input ?? string.Empty;
전달 null
하고 다시 얻을 수 있도록 메서드의 첫 번째 줄로 추가 했습니다 ""
.
'
하면 이제 파이썬에서 제공하는 내용이 repr(a_string)
:)로 표시됩니다.
Hallgrim의 대답은 훌륭하지만 "+", 줄 바꿈 및 들여 쓰기 추가 기능이 나를 위해 기능을 깨고있었습니다. 그 주위에 쉬운 방법은 다음과 같습니다
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;
}
}
}
return literal
읽기 쉽도록 한 줄을 추가 했습니다. literal = literal.Replace("\\r\\n", "\\r\\n\"+\r\n\"");
literal = literal.Replace("/", @"\/");
위해 이것을 추가했습니다 JSON
.
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();
}
}
흥미로운 질문입니다.
더 좋은 방법을 찾을 수 없다면 언제든지 바꿀 수 있습니다.
당신이 그것을 선택한다면, 당신은이 C # 탈출 시퀀스 목록을 사용할 수 있습니다 :
이 목록은 C # FAQ에서 찾을 수 있습니다. 어떤 문자 이스케이프 시퀀스를 사용할 수 있습니까?
nuget 의 Roslyn 's Microsoft.CodeAnalysis.CSharp 패키지 에는이를위한 방법이 있습니다 .
private static string ToLiteral(string valueTextForCompiler)
{
return Microsoft.CodeAnalysis.CSharp.SymbolDisplay.FormatLiteral(valueTextForCompiler, false);
}
분명히 이것은 원래 질문 당시에는 존재하지 않았지만 Google에서 온 사람들에게 도움이 될 수 있습니다.
이스케이프 처리되지 않은 문자열에 JSON 규칙이 충분하고 이미 Newtonsoft.Json
프로젝트에서 사용 하고 있다면 (이는 상당히 큰 오버 헤드가 있음) 다음과 같이이 패키지를 사용할 수 있습니다.
using System;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
Console.WriteLine(ToLiteral( @"abc\n123") );
}
private static string ToLiteral(string input){
return JsonConvert.DeserializeObject<string>("\"" + input + "\"");
}
}
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();
}
}
위 의 Hallgrim의 대답에 ToVerbatim을 추가하려는 시도는 다음과 같습니다.
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;
}
Hallgrim의 대답은 훌륭했습니다. ac # 정규 표현식으로 추가 공백 문자와 줄 바꿈을 구문 분석해야 할 경우를 대비하여 약간의 조정이 있습니다. Google 시트에 삽입하기 위해 직렬화 된 Json 값의 경우이가 필요했으며 코드가 탭, +, 공백 등을 삽입 할 때 문제가 발생했습니다.
provider.GenerateCodeFromExpression(new CodePrimitiveExpression(input), writer, null);
var literal = writer.ToString();
var r2 = new Regex(@"\"" \+.\n[\s]+\""", RegexOptions.ECMAScript);
literal = r2.Replace(literal, "");
return literal;
null
값 을 처리 하고 배열 조회 테이블 사용, 수동 16 진수 변환 및 회피 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();
}
}
암호:
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
이것이 당신이 원하는 것입니까?