C# 문자열 값을 이스케이프된 문자열 리터럴로 변환할 수 있습니까?
C#에서 문자열 값을 코드에서 볼 수 있는 것처럼 문자열 리터럴로 변환할 수 있습니까?탭, 새 줄 등을 탈출 순서로 교체하고 싶습니다.
이 코드인 경우:
Console.WriteLine(someString);
생산물:
Hello
World!
나는 이 코드를 원합니다.
Console.WriteLine(ToLiteral(someString));
생산하는 방법:
\tHello\r\n\tWorld!\r\n
오래전에 이걸 발견했습니다.
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!"
요즘 그레이엄은 로슬린의 마이크로소프트를 사용할 수 있다는 것을 발견했습니다.코드 분석.NuGet의 Csharp 패키지:
private static string ToLiteral(string valueTextForCompiler)
{
return Microsoft.CodeAnalysis.CSharp.SymbolDisplay.FormatLiteral(valueTextForCompiler, false);
}
Regex를 사용합니다.이스케이프( 문자열):
Regex.Escape는 최소 집합의 문자(*, +, ?, |, {, [, ], ^, $, .#, 및 공백)를 이스케이프 코드로 대체하여 탈출합니다.
로슬린의 마이크로소프트에는 이를 위한 방법이 있습니다.코드 분석.NuGet의 Csharp 패키지:
private static string ToLiteral(string valueTextForCompiler)
{
return Microsoft.CodeAnalysis.CSharp.SymbolDisplay.FormatLiteral(valueTextForCompiler, false);
}
원래 질문을 할 때는 이런 것이 없었지만 구글 검색을 통해 여기로 오는 사람들에게 도움이 될 수도 있습니다.
이것은 유니코드와 ASCII 인쇄할 수 없는 문자의 탈출을 포함하여 완전히 작동하는 구현입니다.홀그림의 답처럼 '+' 기호를 삽입하지 않습니다.
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();
}
이 경우에도 모든 유니코드 문자가 빠져 나옵니다.사용자 환경에서 지원하는 경우 해당 부분을 변경하여 제어 문자만 피할 수 있습니다.
// UTF16 control characters
} else if (Char.GetUnicodeCategory(c) == UnicodeCategory.Control) {
literal.Append(@"\u");
literal.Append(((int)c).ToString("x4"));
} else {
literal.Append(c);
}
다음에 대한 모든 탈출 시퀀스를 포함한 보다 구조화된 접근 방식string
모래를char
s, is:
유니코드 문자를 문자 그대로의 동등 문자로 대체하지는 않습니다.그것은 계란도 요리하지 않습니다.
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('\''));
}
}
시도:
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)];
}
}
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;
}
}
}
Smilediver의 답변에 대한 약간의 개선점이 있습니다.ASC 없음을 모두 벗어날 수는 없습니다.II 캐릭터들, 하지만 이것들만 정말 필요합니다.
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# Escape Sequence List를 사용할 수 있습니다.
- \' - 하나의 인용문, 문자 리터럴에 필요함
- \" - 문자열 리터럴에 필요한 이중 따옴표
- \ - 백슬래시
- \0 - 유니코드 문자 0
- \a - 알림(문자 7)
- \b - 백스페이스(문자 8)
- \f - 양식 피드(캐릭터 12)
- \n - 새 행(문자 10)
- \r - 캐리지 리턴(문자 13)
- \t - 가로탭(문자 9)
- \v - 세로 따옴표 (문자 11)
- \uxxxxx - 16진수 값 xxxxx 문자의 유니코드 탈출 순서
- \xn[n][n] - 16진수 값이 nnnn인 문자에 대한 유니코드 탈출 시퀀스(변수 길이 버전의 \uxxxxx)
- \Uxxxxxxxxxxxx - 16진수 값 xxxxxxxxxxx(대리인 생성용) 문자에 대한 유니코드 탈출 시퀀스
이 목록은 C# 질문과 대답에서 확인할 수 있습니다. 어떤 문자 탈출 시퀀스를 사용할 수 있습니까?
탈출하려는 탈출하지 않은 문자열을 JSON 규칙으로 충분하고 이미 Json.NET을 사용하는 경우(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의 대답은 훌륭했습니다.C# 정규식을 사용하여 추가 공백 문자와 줄 바꿈을 구문 분석해야 할 경우에 대한 작은 수정 사항이 있습니다.Google Sheets에 삽입하기 위한 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진수 블 할 때 .동 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
언급URL : https://stackoverflow.com/questions/323640/can-i-convert-a-c-sharp-string-value-to-an-escaped-string-literal
'programing' 카테고리의 다른 글
내부 텍스트별 XPath 선택 (0) | 2023.09.20 |
---|---|
SQLite3 및 여러 프로세스 (0) | 2023.09.20 |
빈 문자열을 허용하는 PowerShell Function Parameters의 유효성을 검사하는 방법은 무엇입니까? (0) | 2023.09.20 |
라라벨:업데이트 시 열이 변경되었는지 관찰자에게 확인 (0) | 2023.09.20 |
도커 네트워킹 - nginx: [emerg] 호스트가 업스트림에서 찾을 수 없음 (0) | 2023.09.20 |