क्या मैं एक बची हुई स्ट्रिंग शाब्दिक C # स्ट्रिंग मान को परिवर्तित कर सकता हूं


195

C # में, क्या मैं स्ट्रिंग मान को एक स्ट्रिंग शाब्दिक में बदल सकता हूं, जिस तरह से मैं इसे कोड में देखूंगा? मैं उनके भागने के दृश्यों के साथ टैब, न्यूलाइन्स आदि को बदलना चाहूंगा।

यदि यह कोड:

Console.WriteLine(someString);

पैदा करता है:

Hello
World!

मुझे यह कोड चाहिए:

Console.WriteLine(ToLiteral(someString));

उत्पादन करना:

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

जवाबों:


180

मुझे मिला:

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!"

1
बस इस विषय से गूगल पाया। यह सबसे अच्छा हो गया है, पुनर्रचना सामान का कोई मतलब नहीं है कि .net हमारे लिए क्या कर सकते हैं
एंडी मॉरिस

16
एक अच्छा है, लेकिन पता है कि लंबे समय तक तार के लिए, यह "+" ऑपरेटरों, newlines और इंडेंटेशन सम्मिलित करेगा। मुझे उस रास्ते को बंद करने का कोई रास्ता नहीं मिला।
टिमवी

2
उलटे का क्या? यदि आपके पास टेक्स्ट कॉन्टैक्स्ट एग्जिट सीक्वेंस के साथ एक फाइल है, तो एस्प्लिडिग के साथ उसका स्पेशल कैरेक्टर बच जाता है? कच्चे संस्करण का उत्पादन कैसे करें?
लुसियानो

1
यदि आप दौड़ते हैं: शून्य मुख्य () {Console.WriteLine (ToLiteral ("test \" \ \\ \\ \ 0 \ a \ b \ f \ n \ r \ t \ v \ uaaaa \\\ blah));) ;; आप देखेंगे कि यह कुछ बच निकलने का ध्यान नहीं रखता है। रोनी ओवरबी ने बताया कि f, अन्य लोग \ a और \ b
कोस्टा

4
वहाँ यह उत्पादन शब्दशः ( @"...") शाब्दिक बनाने के लिए एक रास्ता है?
रोजी 1024

38

Regex.Escape (स्ट्रिंग) के बारे में क्या ?

Regex.Escape वर्णों के न्यूनतम सेट (\, *, +;,;;, {, [, (,), ^, $,।, #, और श्वेत स्थान) से बच जाता है, उन्हें उनके भागने के कोड के साथ बदलकर।


6
+1 कोई विचार नहीं है कि यह नीचे क्यों है। अन्य उत्तर भी बहुत क्रियात्मक हैं और पहियों को सुदृढ़ करने की तरह दिखते हैं
एड्रियानो कारनेइरो

39
यह वह नहीं है जो ओपी पूछ रहा है। यह एक स्ट्रिंग शाब्दिक वापस नहीं करता है, यह एक स्ट्रिंग देता है जिसमें रेगेक्स विशेष वर्ण बच गए हैं। यह बदल Hello World?जाएगा Hello World\?, लेकिन यह एक अमान्य स्ट्रिंग शाब्दिक है।
अथिया

1
मैं @atheaos से सहमत हूं, यह एक बहुत ही अलग प्रश्न का शानदार उत्तर है।
हाइपहुमन जुएल

5
+1 भले ही यह ओपी के सवाल का जवाब नहीं देता है कि यह क्या था (और इसलिए मुझे शायद दूसरों पर शक है) जब मुझे इस सवाल का जवाब मिला। :)
गज़ब ०

यह आवश्यकतानुसार काम नहीं करेगा। रेगेक्स विशेष वर्ण समान नहीं हैं। यह उदाहरण के लिए \ n के लिए काम करेगा, लेकिन जब आपके पास जगह होगी, तो इसे "\" में बदल दिया जाएगा, जो कि C # नहीं करेगा ...
Ernesto

24

संपादित करें: एक अधिक संरचित दृष्टिकोण, जिसमें stringएस और charएस के लिए सभी एस्केप अनुक्रम शामिल हैं ।
यूनिकोड वर्णों को उनके शाब्दिक समकक्ष के साथ प्रतिस्थापित नहीं करता है। या तो अंडे पकाना नहीं है।

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

    }
}

यह सभी एस्केप सीक्वेंस नहीं है;)
TcKs

1
ऊपर दिए गए समाधान से बेहतर काम करता है - और अन्य एस्केप सीक्वेंस आसानी से जोड़े जा सकते हैं।
Arno पीटर्स

स्वीकृत उत्तर में शब्दशः मुझे बोनर्स चला रहा था। यह मेरे उद्देश्य के लिए 100% काम करता है। के साथ बदला गया रेक्सक्स @"[\a\b\f\n\r\t\v\\""/]"और के लिए जोड़ा m_replaceDict.Add("/", @"\/");गया JSON
दिलचस्प-नाम-यहाँ

इसके अलावा, यदि आप चाहते हैं तो आपको इसके लिए संलग्नक उद्धरण जोड़ना होगा।
दिलचस्प-नाम-यहाँ

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

1
शब्दकोश के पहले मूल्य में 3 बैकस्लैश और दो भाषण चिह्न क्यों हैं?
जेम्स येओमन

अच्छा जवाब, @JamesYeoman कि regex पैटर्न से बचने की जरूरत है।
अली मौसवी खेराद

18

प्रयत्न:

var t = HttpUtility.JavaScriptStringEncode(s);

काम नहीं करता। अगर मेरे पास "abc \ n123" है (बिना उद्धरण के, 8 वर्ण), तो मुझे "abc" + \ n + "123" (7 वर्ण) चाहिए। इसके बजाय यह "एबीसी" + "\\" + "\ n123" (9 वर्ण) का उत्पादन करता है। ध्यान दें कि स्लैश को दोगुना कर दिया गया था और इसमें अभी भी दो वर्णों के रूप में "\ n" का एक स्ट्रिंग शाब्दिक है, न कि बचा हुआ चरित्र।
पॉल

2
@Paul क्या आप चाहते हैं कि सवाल क्या है, हालांकि इसके विपरीत है। यह, आपके विवरण के अनुसार, प्रश्न का उत्तर देता है, और इसलिए काम करता है
निधि मोनिका का मुकदमा

मुझे यह सक्रिय निर्देशिका नामों से बचने के लिए उपयोगी पाया गया
chakeda

18

यूनिकोड और एएससीआईआई नॉन प्रिंट करने योग्य वर्णों से बचने सहित पूरी तरह से कार्य कार्यान्वयन। हॉलग्रिम के उत्तर की तरह "+" संकेत नहीं डालता है

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

2
आपको यह Char.GetUnicodeCategory(c) == UnicodeCategory.Controlतय करने के लिए उपयोग करना चाहिए कि क्या इससे बचना है, या जो लोग ASCII नहीं बोलते हैं वे बहुत खुश नहीं होंगे।
हिरणचो

यह स्थिति पर निर्भर करता है कि क्या आपका परिणामी स्ट्रिंग यूनिकोड का समर्थन करने वाले वातावरण में उपयोग किया जाएगा या नहीं।
स्माइलिवर

मैंने input = input ?? string.Empty;विधि की पहली पंक्ति के रूप में जोड़ा , ताकि मैं एक अशक्त संदर्भ अपवाद के बजाय पास nullऔर वापस मिल सके ""
एंडी

अच्छा लगा। उद्धरण संलग्नक को बदलें 'और अब आपके पास क्या है पायथन आपको repr(a_string):) के साथ बॉक्स से बाहर कर देता है ।
z33k

17

हॉलग्रिम का उत्तर उत्कृष्ट है, लेकिन "+", नईलाइन और इंडेंट एडिशन मेरे लिए कार्यक्षमता तोड़ रहे थे। इसके आसपास एक आसान तरीका है:

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
दिलचस्प-नाम-यहाँ

यह 100% सीधे आगे और एकमात्र सही उत्तर है! अन्य सभी उत्तरों ने या तो प्रश्न को नहीं समझा या पहिया का पुनः आविष्कार किया।
bytecode77

दुख की बात है, यह डॉट कोर के तहत काम करने के लिए नहीं मिल सकता है। किसी के पास बेहतर जवाब है?
sk

8

स्मेलेदिवर के उत्तर के लिए यहां थोड़ा सुधार किया गया है, यह सभी नो-एएससीआईआई चार्ट से बच नहीं पाएगा लेकिन केवल इनकी वास्तव में आवश्यकता है।

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

8

दिलचस्प सवाल।

यदि आपको एक बेहतर तरीका नहीं मिल रहा है, तो आप हमेशा बदल सकते हैं।
यदि आप इसके लिए चयन कर रहे हैं, तो आप इस C # एस्केप अनुक्रम सूची का उपयोग कर सकते हैं :

  • \ '- एकल शब्द, वर्ण शाब्दिक के लिए आवश्यक
  • \ "- डबल उद्धरण, स्ट्रिंग शाब्दिक के लिए आवश्यक
  • \ - बैकस्लैश
  • \ 0 - यूनिकोड वर्ण 0
  • \ a - चेतावनी (चरित्र 7)
  • \ b - बैकस्पेस (अक्षर 8)
  • \ f - फ़ॉर्म फ़ीड (वर्ण 12)
  • \ n - नई पंक्ति (वर्ण 10)
  • \ r - कैरिज रिटर्न (चरित्र 13)
  • \ t - क्षैतिज टैब (वर्ण 9)
  • \ v - कार्यक्षेत्र उद्धरण (वर्ण 11)
  • \ uxxxx - हेक्स मान xxxx के साथ चरित्र के लिए यूनिकोड एस्केप अनुक्रम
  • \ xn [एन] [एन] [एन] - हेक्स मान nnnn (चर लंबाई संस्करण \ uxxxx) के साथ चरित्र के लिए यूनिकोड एस्केप अनुक्रम
  • \ Uxxxxxxxx - हेक्स मान xxxxxxxx (सरोगेट्स जनरेट करने के लिए) के साथ यूनिकोड एस्केप सीक्वेंस

इस सूची को C # अक्सर पूछे जाने वाले प्रश्नों में पाया जा सकता है कि चरित्र से बचने के क्रम क्या उपलब्ध हैं?


2
यह लिंक अब काम नहीं करता है, लिंक-ओनली उत्तरों को हतोत्साहित करने का एक पाठ्यपुस्तक उदाहरण है।
जेम्स

बहुत सही, @ नाम, लेकिन जेमी ट्वेल्स के लिए धन्यवाद फिर से जानकारी उपलब्ध है: +1:
नेल्सन रीस

5

रोसलिन के Microsoft.CodeAnalysis.CSharp पैकेज में nuget पर इसके लिए एक विधि है :

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

जाहिर है कि यह मूल प्रश्न के समय मौजूद नहीं था, लेकिन ऐसे लोगों की मदद कर सकता है जो Google से यहां आते हैं।


3

यदि 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 + "\"");
    }
}

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

2

हॉलग्रिम के उपरोक्त उत्तर के लिए 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;
}

1

हॉलग्रिम का उत्तर उत्कृष्ट था। यदि आपको अतिरिक्त व्हॉट्सएप वर्णों को पार्स करने और एसी # नियमित अभिव्यक्ति के साथ लाइनब्रीक करने की आवश्यकता है, तो यहां एक छोटा ट्विक है। मुझे इस बात की आवश्यकता थी कि गूगल शीट में प्रविष्टि के लिए एक क्रमबद्ध 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;

-1

मैं अपना स्वयं का कार्यान्वयन प्रस्तुत करता हूं, जो 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();
  }
}

-7

कोड:

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

क्या ये वही है जो तुम चाहते हो?


मेरे पास someString1 है, लेकिन यह एक फ़ाइल से पढ़ा जाता है। मैं चाहता हूं कि यह कुछ विधि को कॉल करने के बाद someString2 के रूप में दिखाई दे।
हॉलग्रिम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.