2009-09-01 85 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