Can I expand a string that contains C# literal expressions at runtime

后端 未结 4 781
后悔当初
后悔当初 2020-11-29 11:36

If I have a string that contains a c# string literal expression can I \"expand\" it at runtime

    public void TestEvaluateString()
    {
        string Dumm         


        
4条回答
  •  孤街浪徒
    2020-11-29 11:53

    If you're just looking to do "simple" escape characters as defined on the Microsoft site, you can use this routine and save importing external libs:

    public static class StringExtensions
    {
        /* https://msdn.microsoft.com/en-us/library/aa691087(v=vs.71).aspx */
        private readonly static SortedDictionary EscapeMap = new SortedDictionary
        {
            { '\'', '\'' },
            { '"', '\"' },
            { '\\', '\\' },
            { '0', '\0' },
            { 'a', '\a' },
            { 'b', '\b' },
            { 'f', '\f' },
            { 'n', '\n' },
            { 'r', '\r' },
            { 't', '\t' },
            { 'v', '\v' },
        };
    
        public static string UnescapeSimple(this string escaped)
        {
            if (escaped == null)
                return escaped;
    
            var sb = new StringBuilder();
    
            bool inEscape = false;
            var s = 0;
            for (var i = 0; i < escaped.Length; i++)
            {
                if (!inEscape && escaped[i] ==  '\\')
                {
                    inEscape = true;
                    continue;
                }
    
                if (inEscape)
                {
                    char mapChar;
                    if (EscapeMap.TryGetValue(escaped[i], out mapChar))
                    {
                        sb.Append(escaped.Substring(s, i - s - 1));
                        sb.Append(mapChar);
    
                        s = i + 1;
                    }
                    inEscape = false;
                }
            }
    
            sb.Append(escaped.Substring(s));
    
            return sb.ToString();
        }
    }
    

    Here's a unit test to prove it:

        [TestMethod]
        public void UnescapeSimpleTest()
        {
            var noEscapes = @"This is a test".UnescapeSimple();
            Assert.AreEqual("This is a test", noEscapes, nameof(noEscapes));
    
            var singleEscape = @"\n".UnescapeSimple();
            Assert.AreEqual("\n", singleEscape, nameof(singleEscape));
    
            var allEscape = @"\'\""\\\0\a\b\f\n\r\t\v".UnescapeSimple();
            Assert.AreEqual("\'\"\\\0\a\b\f\n\r\t\v", allEscape, nameof(allEscape));
    
            var textInEscapes = @"\tthis\n\ris\\a\ntest".UnescapeSimple();
            Assert.AreEqual("\tthis\n\ris\\a\ntest", textInEscapes, nameof(textInEscapes));
    
            var backslashNoEscapes = @"\,\h\qtest".UnescapeSimple();
            Assert.AreEqual(@"\,\h\qtest", backslashNoEscapes, nameof(backslashNoEscapes));
    
            var emptyStr = "".UnescapeSimple();
            Assert.AreEqual("", emptyStr, nameof(emptyStr));
    
            // Prove Enviroment.NewLine is "\r\n" and not "\n\r" (Windows PC)
            var newLine = @"\r\n".UnescapeSimple();
            Assert.AreEqual(Environment.NewLine, newLine, nameof(newLine));
    
            // Double check prior test (Windows PC)
            var newLineWrong = @"\n\r".UnescapeSimple();
            Assert.AreNotEqual(Environment.NewLine, newLineWrong, nameof(newLineWrong));
        }
    

    Feel free to tweak the EscapeMap or rename the function UnescapeSimple (awkward I know).

    Note that this solution doesn't handle Unicode escape characters or hex or octal, it just handles the simple single character ones.

提交回复
热议问题