2009-09-01 81 views
1

有人可以把一个正则表达式来:
&:正则表达式表达挑战

  1. 发现开头[%和%结束]块是块内
  2. 与替换所有XML特殊字符QUOT; '&'; & lt; & gt; amp; & amp;
  3. 离开<%=%>或<%#%>的是,除了确保有后<%#或<%的空间=和%之前>例如<%= Integer.MaxValue%>应成为之间的一切<%= Integer.MaxValue%>

源:

[% 'test' <mtd:ddl id="asdf" runat="server"/> & <%= Integer.MaxValue% > %] 

结果:

&apos;test&apos; &lt;mtd:ddl id=&quot;asdf&quot; runat=&quot;server&quot;/&gt; &amp; <%= Integer.MaxValue %> 
+4

您所描述的逻辑是由性格比正则表达式解析字符串的性格变得更多的任务。 – Cascabel 2009-09-01 16:05:21

+0

同意Jefromi。这是一些代码工作(可能利用一或两个正则表达式) – 2009-09-01 16:10:24

回答

2

使用2个正则表达式。第一个匹配一般形式,第二个处理内部管道。

对于XML编码,我在System.Security中使用了一个不起眼的小方法:SecurityElement.Escape Method。我在下面的代码中完全限定了它的重点。另一种选择是使用HttpUtility.HtmlEncode method,但可能涉及对System.Web的引用,具体取决于您使用的位置。

string[] inputs = { @"[% 'test' <mtd:ddl id=""asdf"" runat=""server""/> & <%= Integer.MaxValue %> %]", 
    @"[% 'test' <mtd:ddl id=""asdf"" runat=""server""/> & <%=Integer.MaxValue %> %]", 
    @"[% 'test' <mtd:ddl id=""asdf"" runat=""server""/> & <%# Integer.MaxValue%> %]", 
    @"[% 'test' <mtd:ddl id=""asdf"" runat=""server""/> & <%#Integer.MaxValue%> %]", 
}; 
string pattern = @"(?<open>\[%)(?<content>.*?)(?<close>%])"; 
string expressionPattern = @"(?<content>.*?)(?<tag><%(?:[=#]))\s*(?<expression>.*?)\s*%>"; 

foreach (string input in inputs) 
{ 
    string result = Regex.Replace(input, pattern, m => 
     m.Groups["open"].Value + 
     Regex.Replace(m.Groups["content"].Value, expressionPattern, 
      expressionMatch => 
      System.Security.SecurityElement.Escape(expressionMatch.Groups["content"].Value) + 
      expressionMatch.Groups["tag"].Value + " " + 
      expressionMatch.Groups["expression"].Value + 
      " %>" 
     ) + 
     m.Groups["close"].Value 
    ); 

    Console.WriteLine("Before: {0}", input); 
    Console.WriteLine("After: {0}", result); 
} 

结果:

Before: [% 'test' <mtd:ddl id="asdf" runat="server"/> & <%= Integer.MaxValue %> %] 
After: [% &apos;test&apos; &lt;mtd:ddl id=&quot;asdf&quot; runat=&quot;server&quot;/&gt; &amp; <%= Integer.MaxValue %> %] 
Before: [% 'test' <mtd:ddl id="asdf" runat="server"/> & <%=Integer.MaxValue %> %] 
After: [% &apos;test&apos; &lt;mtd:ddl id=&quot;asdf&quot; runat=&quot;server&quot;/&gt; &amp; <%= Integer.MaxValue %> %] 
Before: [% 'test' <mtd:ddl id="asdf" runat="server"/> & <%# Integer.MaxValue%> %] 
After: [% &apos;test&apos; &lt;mtd:ddl id=&quot;asdf&quot; runat=&quot;server&quot;/&gt; &amp; <%# Integer.MaxValue %> %] 
Before: [% 'test' <mtd:ddl id="asdf" runat="server"/> & <%#Integer.MaxValue%> %] 
After: [% &apos;test&apos; &lt;mtd:ddl id=&quot;asdf&quot; runat=&quot;server&quot;/&gt; &amp; <%# Integer.MaxValue %> %] 

编辑:,如果你不小心保存开/最终结果关闭[%%]然后将模式更改为:

string pattern = @"\[%(?<content>.*?)%]"; 

然后务必删除对m.Groups["open"].Value和0的引用。

+0

有趣的是,如果我从文件中读取字符串,这没有用吗?字符串与您使用的字符串(第一个字符串)完全相同,除非不是双引号(“”)。 ? – epitka 2009-09-04 18:42:52

+0

@epitka:数据全部在1行还是分开?在这种情况下,它将不匹配(即不跨越线)。第二组双引号仅用于在代码中使用@符号将其作为逐字字符串进行转义,因此实际输入自然只会包含一个双引号。这就是说,这不重要。我将示例数据放在一个文本文件中,并将第一行更改为:string [] inputs = File.ReadAllLines(@“c:\ temp.txt”)并且它工作正常。还尝试用一个字符串使用File.ReadAllText(...)。你能告诉我们你是如何从文件中读取它以及数据是怎样的? – 2009-09-04 19:03:57

+0

您可以在两个Regex.Replace语句的末尾添加RegexOptions.Singleline选项(将其添加为最终参数,其中有一个重载的Replace方法),如果数据跨越多行,这将使其起作用。 – 2009-09-04 19:10:00

1
private void button1_Click(object sender, EventArgs e) 
     { 
      Regex reg = new Regex(@"\[%(?<b1>.*)%\]"); 
      richTextBox1.Text= reg.Replace(textBox1.Text, new MatchEvaluator(f1)); 
     } 

     static string f1(Match m) 
     { 
      StringBuilder sb = new StringBuilder(); 
      string[] a = Regex.Split(m.Groups["b1"].Value, "<%[^%>]*%>"); 
      MatchCollection col = Regex.Matches(m.Groups["b1"].Value, "<%[^%>]*%>"); 
      for (int i = 0; i < a.Length; i++) 
      { 
       sb.Append(a[i].Replace("&", "&amp;").Replace("'", "&apos;").Replace("\"", "&quot;").Replace("<", "&lt;").Replace(">", "&gt;")); 
       if (i < col.Count) 
        sb.Append(col[i].Value); 
      } 
      return sb.ToString(); 
     } 

的Test1:

[% 'test' <mtd:ddl id="asdf" runat="server"/> & <%= Integer.MaxValue%> fdas<% hi%> 321%] 

结果:

&apos;test&apos; &lt;mtd:ddl id=&quot;asdf&quot; runat=&quot;server&quot;/&gt; &amp; <%= Integer.MaxValue%> fdas<% hi%> 321