如果我有一个包含c#字符串文字表达式的字符串,我可以在运行时“展开”它
public void TestEvaluateString()
{
string Dummy = EvalString( @"Contains \r\n new line");
Debug.Assert(Dummy == "Contains \r\n new line");
}
private string EvalString(string input)
{
return "Contains \r\n new line";
}
与Can I convert a C# string value to an escaped string literal相似,但相反?
答案 0 :(得分:10)
与Mikael的答案类似,但使用的是CSharpCodeProvider:
public static string ParseString(string txt)
{
var provider = new Microsoft.CSharp.CSharpCodeProvider();
var prms = new System.CodeDom.Compiler.CompilerParameters();
prms.GenerateExecutable = false;
prms.GenerateInMemory = true;
var results = provider.CompileAssemblyFromSource(prms, @"
namespace tmp
{
public class tmpClass
{
public static string GetValue()
{
return " + "\"" + txt + "\"" + @";
}
}
}");
System.Reflection.Assembly ass = results.CompiledAssembly;
var method = ass.GetType("tmp.tmpClass").GetMethod("GetValue");
return method.Invoke(null, null) as string;
}
使用通配符字典并在字符串中替换它们可能会更好。
答案 1 :(得分:3)
不确定这是否是最简单的方法,但通过引用Microsoft.JScript
命名空间,您可以使用javascript eval
函数重新解析它。
这是对底部代码的测试
var evalToString = Evaluator.MyStr("test \\r\\n test");
这会将\ r变为回车。
实施
public class Evaluator
{
public static object MyStr(string statement)
{
return _evaluatorType.InvokeMember(
"MyStr",
BindingFlags.InvokeMethod,
null,
_evaluator,
new object[] { statement }
);
}
static Evaluator()
{
ICodeCompiler compiler;
compiler = new JScriptCodeProvider().CreateCompiler();
CompilerParameters parameters;
parameters = new CompilerParameters();
parameters.GenerateInMemory = true;
CompilerResults results;
results = compiler.CompileAssemblyFromSource(parameters, _jscriptSource);
Assembly assembly = results.CompiledAssembly;
_evaluatorType = assembly.GetType("Evaluator.Evaluator");
_evaluator = Activator.CreateInstance(_evaluatorType);
}
private static object _evaluator = null;
private static Type _evaluatorType = null;
private static readonly string _jscriptSource =
@"package Evaluator
{
class Evaluator
{
public function MyStr(expr : String) : String
{
var x;
eval(""x='""+expr+""';"");
return x;
}
}
}";
}
答案 2 :(得分:3)
Regex.Unescape
将是我的首选方法。
答案 3 :(得分:2)
如果你只是想做什么"简单"转义Microsoft site上定义的转义字符,您可以使用此例程并保存导入外部库:
public static class StringExtensions
{
/* https://msdn.microsoft.com/en-us/library/aa691087(v=vs.71).aspx */
private readonly static SortedDictionary<char, char> EscapeMap = new SortedDictionary<char, char>
{
{ '\'', '\'' },
{ '"', '\"' },
{ '\\', '\\' },
{ '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();
}
}
这是一个证明它的单元测试:
[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));
}
随意调整EscapeMap或重命名函数UnescapeSimple(我知道这很尴尬)。
请注意,此解决方案不处理Unicode转义字符或十六进制或八进制,它只处理简单的单字符。