Feedback

C# - Dynamischer Regex.Replace

Veröffentlicht von am 5/1/2013
(2 Bewertungen)
Ich brauchte eine Möglichkeit einen String mit Hilfe von Regex'en zu ersetzen, dabei aber auch Groups einzusetzen und wieder in den Zielstring einzufügen.

Dafür braucht man die Überladung mit dem Delegate auf eine Replace-Methode.

Wenn die Regex'en nicht fix sind, lässt sich das mit statischem Code nicht erledigen.

Wohl aber mit Code, der on-the-fly kompiliert wird.

Die generelle Idee ist, dass man sowohl die Regex, als auch den Ersetzungscode irgendwo als Input hat (z.B. als XML) und dann im Fluge eine Klasse erzeugt, die die Ersetzung vornimmt.

Ich habe eine XML-Datei benutzt, die mir die Daten zur Verfügung stellt:


<?xml version="1.0"?>
<ParamList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Params>
<Param>
<Name>Grafiken</Name>
<Regex>\\[img\\](?'Link'.+?)\\[/img\\]</Regex>
<RegexOptions>RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase</RegexOptions>
<Code>"&lt;img src=\"" + match.Groups["Link"].Value + "\"&gt;"</Code>
</Param>
<Param>
<Name>Fetter Text</Name>
<Regex>\\[b\\](?'Text'.+?)\\[/b?\\]</Regex>
<RegexOptions>RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase</RegexOptions>
<Code>"&lt;strong&gt;" + match.Groups["Text"].Value + "&lt;/strong&gt;"</Code>
</Param>
</Params>
</ParamList>


Und hier ein Stück Test-Text zum Ausprobieren:


Das ist ein {b}fetter{/b} Text.

{img}test.jpg{/img}


"[" und "]" anstelle von "{" und "}" benutzen!
[Serializable()]
public class ParamList
{
    [XmlArrayItem("Param")]
    public Param[] Params;
}

[Serializable()]
public class Param
{
    public String Name;
    public String Regex;
    public String RegexOptions;
    public String Code;
}

public class ReplaceHelper
{
    private Boolean Replace(ref String text)
    {
        ParamList pl;           

        using (FileStream fs = new FileStream("params.xml", FileMode.Open
            , FileAccess.Read, FileShare.Read))
        {
            XmlSerializer xmls;

            xmls = new XmlSerializer(typeof(ParamList));
            pl = (ParamList)(xmls.Deserialize(fs));
        }            
        foreach (Param param in pl.Params)
        {
            CSharpCodeProvider cscp;
            CompilerParameters cp;
            CompilerResults cr;
            Object replacer;
            StringBuilder errorText;
            StringBuilder code;                

            code = new StringBuilder();
            errorText = new StringBuilder();
            code.AppendLine("using System;");
            code.AppendLine("using System.Text.RegularExpressions;");
            code.AppendLine();
            code.AppendLine("public class RegexReplacer");
            code.AppendLine("{");
            code.AppendLine("  private static readonly Regex s_Regex = new Regex(\"" 
                + param.Regex + "\", " + param.RegexOptions + ");");
            code.AppendLine();
            code.AppendLine("  private String Replace(Match match)");
            code.AppendLine("  {");
            code.AppendLine("    return (" + param.Code + ");");
            code.AppendLine("  }");
            code.AppendLine();
            code.AppendLine("  public String Replace(String text)");
            code.AppendLine("  {");
            code.AppendLine("    return(s_Regex.Replace(text, new MatchEvaluator(this.Replace)));");
            code.AppendLine("  }");
            code.AppendLine("}");
            cscp = new Microsoft.CSharp.CSharpCodeProvider();
            cp = new System.CodeDom.Compiler.CompilerParameters();
            cp.ReferencedAssemblies.Add("System.dll");
            cr = cscp.CompileAssemblyFromSource(cp, code.ToString());
            if ((cr.Errors != null) && (cr.Errors.Count > 0))
            {
                foreach (CompilerError error in cr.Errors)
                {
                    errorText.Append(error.ErrorText);
                    errorText.Append("(ln ");
                    errorText.Append(error.Line);
                    errorText.AppendLine(")");
                }
                errorText.AppendLine();
                errorText.Append(code.ToString());
                text = errorText.ToString();
                return (false);
            }
            replacer = cr.CompiledAssembly.CreateInstance("RegexReplacer");
            text = replacer.GetType().GetMethod("Replace").Invoke(replacer
                , new Object[] { text }).ToString();
        }
        return (true);
    }
}

Kommentare zum Snippet

 

Logge dich ein, um hier zu kommentieren!