2012年11月18日 星期日

Validation-Engine研究



以前在使用者輸入的TextBox我們要進行資料檢測,我都使用ASP.NETRequiredFieldValidator,但一直以來感覺他的效果不是很好,因為複雜一點的規則,基本上還是自己要去寫Javascript,再來是當使用者輸入錯誤時出現提示訊息時,出現的文字會去擠壓原本的表格,這次因為要檢測使用者輸入是否為數字,想說找一下JQuery的作法,找的過程中發現有JQuery.Valdation,突然想到之前有聽過JQuery有整套的驗證機制,找了一下看到黑暗執行緒大介紹了一套Validation-Engine,看了一下效果感覺真的很不錯,因此決定來研究一下

一開始因為不曉得怎麼使用,而且看到不同的範例用的Validation-Engine都是不同版本且差異頗大,因此花了不少時間去找這個元件能夠Run起來,走了不少冤望路,主要只要以下幾個檔案就能夠執行(有時候直接去看作者原始碼比較快)
validationEngine.jquery.css
有兩種,一種為紅色系,一種為黑色系,個人覺得紅色比較好看
jquery.validationEngine-zh_TW.js
語言檔,判斷資料正確與否的正則表達式也是寫在這裡
jquery.validationEngine.js
元件主程式

知道了如何使用後再來就是測試自己所需要的功能,測試的過程中碰到一些問題記錄如下:
原本在1.7.2的版本中提供了驗證長度的方法,但在最新的2.6.1中不支援這個方法,不太明白為什麼作者將這個方法移除,照理說這個應該非常常用
所以只能夠用自訂Function

Function的寫法可以參考以下,但我尚未測試過
方法一
1、注:調整一個漢字字符長度為2,一個英文字符長度為1 
for (var i = 0; i < val.length; i++)  
 { 
   len = len + ((val.charCodeAt(i) >= 0x4e00 && val.charCodeAt(i) <= 0x9fa5) ? 2 : 1);  
 } 
2validationEngine 字符長度問題(漢字字符,英文字符長度) 
var len = field.val().length;替換為
var len = 0; 
var val = field.val(); 
for (var i = 0; i < val.length; i++)  
{ 
len = len + ((val.charCodeAt(i) >= 0x4e00 && val.charCodeAt(i) <= 0x9fa5) ? 2 : 1);  
} 

方法二
function checkDate(oTextbox) {
var regex = new RegExp("^(?:(?:([0-9]{4}(-|\/)(?:(?:0?[1,3-9]|1[0-2])(-|\/)(?:29|30)|((?:0?[13578]|1[02])(-|\/)31)))|([0-9]{4}(-|\/)(?:0?[1-9]|1[0-2])(-|\/)(?:0?[1-9]|1\\d|2[0-8]))|(((?:(\\d\\d(?:0[48]|[2468][048]|[13579][26]))|(?:0[48]00|[2468][048]00|[13579][26]00))(-|\/)0?2(-|\/)29))))$");
if (!regex.test(oTextbox)) {
return false;
}
return true;
}
方法三Client Side and Server Side
http://www.eion.com.tw/Blogger/?Pid=1047

再來是日期輸入的驗證,元件中預設的驗證日期的正則表達式其實不太能夠真的將各種狀況擋住,我搜尋了網路上的很多方法進行測試,效果都不好,無法完全處理各種狀況,最後是用一種偷懶的方式,就是在TextBox上設定一個日期元件讓使用者日期只能用選的,但從Framework 2.0後,當我們將TextBox設定為唯讀,則程式是無法存取到該TextBox的值,因此這邊要繞個彎,在TextBox設定OnBlurreturn掉使用者企圖在輸入視窗上做任何事

最後是ajax驗證
一開始就碰到問題,因為作者網站的範例不能跑,而範例中是用php寫的我無法觀察要回傳什麼json的值給元件接,如果你直接去跑作者ajax驗證那頁會發現,那一頁傳回的是空值,所以當然無法正常運作,因此找了幾個人家做好的範例參考
單純的流氓那篇算是寫得相當清楚,不過裡面有誤解了原作者的地方,就是他請大家去改原作者的元件,因為我不太相信這個元件這麼久了會有需要去改元件才能使用的問題,因此決定查個清楚,還好在RIA之家的範例是可以跑的
這邊是以2.2版的做範例,我比對過跟2.6.1要做驗證的地方一模一樣,因此我想如果他能夠正常運作,那麼他回傳的json值也一定是正確,所以我手動的去跑他ajax驗證那頁(還好可以看到程式碼)
果然他有正常傳回值,如下:
["user",true]
這樣我們就知道自己所寫的後端驗證要傳回什麼值了,因此事實上是不需要修改原作者元件的。
註:
這邊可以有三個參數
["user",true,”請輸入123”]
第一個參數為TextBoxid名稱,第二個參數為驗證成功或失敗,第三個參數則是要給使用者看到什麼訊息

以下是ajax呼叫所需要的一些參數
"ajaxTest":{
"url":"webservice.asmx/Vaildate",
"extraData":"extraData=xxx",
"alertTextOk":"*ok",
"alertText":"*fail",
"alertTextLoad":"*正在確認,請稍等。"
說明一下extraData的作用為用get的方式去傳回後端當作參數使用

作者在js\languages裡提供了各種語系檔,連中文都有,不過可以多利用jquery.validationEngine-zh_TW.js去作搜尋人家已經做好的各式驗證
要如何動態挑選適合使用者的語系,可以參考以下
http://pramaire.pixnet.net/blog/post/45322227-jquery%E5%8F%96%E7%B6%B2%E9%A0%81url%E5%8F%83%E6%95%B8-%26-%E5%8B%95%E6%85%8B%E8%BC%89%E5%85%A5js%E6%AA%94

最後,因為之前都是使用post的方式去送參數到後端,所以一送出資料以後就出現「無法辨認要求格式,因為URL 未預期地以{0} 結束。」,查了一下發現在這邊
type: options.ajaxFormValidationMethod,
ajaxFormValidationMethod定義為使用get的方式
ajaxFormValidationMethod: 'get',
因此我手動將元件改為post是可以正常運作的,因此查了一下發現預設的get是關閉的,因此程式無法運作,所以將以下這段加入web.config就正常了
   
       
       
   
如果要關閉這兩個服務的話,則加入以下這段
 
   
   
 

這裡稍微深入的研究一下
   
       
       
   

似乎可以只讓localhost呼叫
似乎可以只讓某些服務才有作用

也有看到像下面的寫法
 
   
     
       
       
     
   
 
但這些就要再找時間仔細測試了

參考網址
謙卑式jQuery檢核-動態訊息
Validation-Engine介紹
NuGet程式包-改良ASP.NET MVC驗證訊息顯示
使用jQuery.validate.unobtrusive.js
Example of Using JQuery Validation Engine Plugin with ASP.NET Controls
Validation-Engine討論區
Validation-Engine作者網站
jQuery inline form validation Engine
jquery.validationEngine ajax驗證 不通過也提交表單
jQuery Validation Engine的表單驗證與字段ajax驗證

關鍵字
jquery 檢查數字
jquery.validate.unobtrusive.js
jquery.validate.inline
validationEngine.jquery.css
validation engine length
validation engine "asp.net" ashx
validationEngine ajax
無法辨認要求格式,因為 URL 未預期地以 結束
web.config web Services protocols

日期正則表達式
正則 "yyyy/mm/dd"
一些正則表達式的參考,只有測試過日期的部分,都不太能用
http://mengqingyu.iteye.com/blog/426454

2012年11月17日 星期六

Javascript Chart收集

Highcharts-InteractiveJavaScriptchartsforyourwebpage
http://www.highcharts.com/
非常漂亮,不過商用要買License

dygraphsJavaScriptVisualizationLibrary
http://www.danvk.org/dygraphs/
JavaScript圖表,看起來很像Flash,像GoogleAnalytics一樣.

flotr2
http://www.humblesoftware.com/flotr2/
HTML5JavaScriptChartLibrary

20FreshJavaScriptDataVisualizationLibraries
http://sixrevisions.com/javascript/20-fresh-javascript-data-visualization-libraries/

gRaphaël—ChartingJavaScriptLibrary
http://g.raphaeljs.com/
JavaScript圓餅圖、長條圖

開發人員指南-Google圖表API-GoogleCode
http://code.google.com/intl/zh-TW/apis/chart/
GoogleChartAPI

flot-ProjectHostingonGoogleCode
http://code.google.com/p/flot/
jQueryflot餵jsonformat來畫圖.

JavaScriptDiagramBuilder
http://www.lutanho.net/diagram/
畫面普通,但是基本實用.

PlotKit-JavascriptChartPlotting|liquidx
http://www.liquidx.net/plotkit/
JavaScriptchartPlot

EmpriseJavaScriptCharts™::100%PureJavaScriptCharts
http://www.ejschart.com/
JavaScriptChart可以有像GoogleAnalytics的效果.

JSCharts–FreeJavaScriptcharts
http://www.jscharts.com/
JSChart,商用要付費.

YUI2:Charts
http://developer.yahoo.com/yui/charts/
YUIChart

jQuerySparklines
http://omnipotent.net/jquery.sparkline/
要做股市那種會跑的圖,可以用這個~

moBlur.org-jQueryFlot-Plots,CanvasandCharts
http://blog.shinylittlething.com/workshop/flot_intro/

Bluff:BeautifulgraphsinJavaScript
http://bluff.jcoglan.com/
非常輕巧的Chatlibrary.

javascriptRRD|freshmeat.net
http://freshmeat.net/projects/javascriptrrd
JavaScriptRRD

5JavascriptChartAlternatives
http://www.reynoldsftw.com/2009/03/javascript-chart-alter...

DHTML:DrawLine,Ellipse,Oval,Circle,Polyline,Polygon,TrianglewithJavaScript
http://www.walterzorn.com/jsgraphics/jsgraphics_e.htm

jQueryVisualizePlugin:AccessibleCharts
http://www.filamentgroup.com/lab/jquery_visualize_plugin_...
jQueryTable畫成圖表.

Graphing/ChartingDataonWebPages:JavaScriptSolutions
http://sixrevisions.com/javascript/graph_chart_plot_data_...
JavaScriptFlotLibrary.

YUIFlot
http://github.com/bluesmoon/yui-flot
YUIFlot

28RichDataVisualizationTools-InsideRIA
http://www.insideria.com/2009/12/28-rich-data-visualizati...
AJAXChart

AJAXAPIsPlayground
http://code.google.com/apis/ajax/playground/
VisualizationAPI部份,全部都是Chart.

Morris.js
http://oesmith.github.com/morris.js/
jQuerypluginSVG

d3.js
http://mbostock.github.com/d3/
做3D動畫圖表

資料來源
http://wowtree.com/tree.php?aid=864

正則表達式收集

先將收集到的放在這邊,找時間在做測試與驗證

匹配中文字符的正則表達式: [u4e00-u9fa5]
評注:匹配中文還真是個頭疼的事,有了這個表達式就好辦了

匹配雙字節字符(包括漢字在內):[^x00-xff]
評注:可以用來計算字符串的長度(一個雙字節字符長度計2,ASCII字符計1)
匹配空白行的正則表達式:ns*r
評注:可以用來刪除空白行
匹配HTML標記的正則表達式:<(S*?)[^>]*>.*?|<.*? />
評注:網上流傳的版本太糟糕,上面這個也僅僅能匹配部分,對於複雜的嵌套標記依舊無能為力
匹配首尾空白字符的正則表達式:^s*|s*$
評注:可以用來刪除行首行尾的空白字符(包括空格、制表符、換頁符等等),非常有用的表達式
匹配Email地址的正則表達式:w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*
評注:表單驗證時很實用
匹配網址URL的正則表達式:[a-zA-z]+://[^s]*
評注:網上流傳的版本功能很有限,上面這個基本可以滿足需求
匹配帳號是否合法(字母開頭,允許5-16字節,允許字母數字下劃線):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
評注:表單驗證時很實用
匹配國內電話號碼:d{3}-d{8}|d{4}-d{7}
評注:匹配形式如 0511-4405222 或 021-87888822
匹配騰訊QQ號:[1-9][0-9]{4,}
評注:騰訊QQ號從10000開始
匹配中國郵政編碼:[1-9]d{5}(?!d)
評注:中國郵政編碼為6位數字
匹配身份證:d{15}|d{18}
評注:中國的身份證為15位或18位
匹配ip地址:d+.d+.d+.d+
評注:提取ip地址時有用

最強驗證日期的正則表達式,添加了閏年的驗證

這個日期正則表達式支持
YYYY-MM-DD
YYYY/MM/DD
YYYY_MM_DD
YYYY.MM.DD的形式

match : 2008-2-29 2008/02/29

not match : 2008-2-30     2007-2-29


完整的正則表達式如下:
((^((1[8-9]\d{2})|([2-9]\d{3}))([-\/\._])(10|12|0?[13578])([-\/\._])(3[01]|[12][0-9]|0?[1-9])$)|(^((1[8-9]\d{2})|([2-9]\d{3}))([-\/\._])(11|0?[469])([-\/\._])(30|[12][0-9]|0?[1-9])$)|(^((1[8-9]\d{2})|([2-9]\d{3}))([-\/\._])(0?2)([-\/\._])(2[0-8]|1[0-9]|0?[1-9])$)|(^([2468][048]00)([-\/\._])(0?2)([-\/\._])(29)$)|(^([3579][26]00)([-\/\._])(0?2)([-\/\._])(29)$)|(^([1][89][0][48])([-\/\._])(0?2)([-\/\._])(29)$)|(^([2-9][0-9][0][48])([-\/\._])(0?2)([-\/\._])(29)$)|(^([1][89][2468][048])([-\/\._])(0?2)([-\/\._])(29)$)|(^([2-9][0-9][2468][048])([-\/\._])(0?2)([-\/\._])(29)$)|(^([1][89][13579][26])([-\/\._])(0?2)([-\/\._])(29)$)|(^([2-9][0-9][13579][26])([-\/\._])(0?2)([-\/\._])(29)$))
閏年的2月份有29天,因此匹配閏年日期格式為YYYY-MM-DD的正則表達式為:

(([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29

最後,將平年和閏年的日期驗證表達式合併,我們得到最終的驗證日期格式為YYYY-MM-DD的正則表達式為:

(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29)

DD/MM/YYYY格式的正則驗證表達式為:

(((0[1-9]|[12][0-9]|3[01])/((0[13578]|1[02]))|((0[1-9]|[12][0-9]|30)/(0[469]|11))|(0[1-9]|[1][0-9]|2[0-8])/(02))/([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3}))|(29/02/(([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00)))


匹配特定數字:
^[1-9]d*$    //匹配正整數
^-[1-9]d*$   //匹配負整數
^-?[1-9]d*$   //匹配整數
^[1-9]d*|0$  //匹配非負整數(正整數 + 0)
^-[1-9]d*|0$   //匹配非正整數(負整數 + 0)
^[1-9]d*.d*|0.d*[1-9]d*$   //匹配正浮點數
^-([1-9]d*.d*|0.d*[1-9]d*)$  //匹配負浮點數
^-?([1-9]d*.d*|0.d*[1-9]d*|0?.0+|0)$  //匹配浮點數
^[1-9]d*.d*|0.d*[1-9]d*|0?.0+|0$   //匹配非負浮點數(正浮點數 + 0)
^(-([1-9]d*.d*|0.d*[1-9]d*))|0?.0+|0$  //匹配非正浮點數(負浮點數 + 0)
評注:處理大量數據時有用,具體應用時注意修正
匹配特定字符串:
^[A-Za-z]+$  //匹配由26個英文字母組成的字符串
^[A-Z]+$  //匹配由26個英文字母的大寫組成的字符串
^[a-z]+$  //匹配由26個英文字母的小寫組成的字符串
^[A-Za-z0-9]+$  //匹配由數字和26個英文字母組成的字符串
^w+$  //匹配由數字、26個英文字母或者下劃線組成的字符串

在使用RegularExpressionValidator驗證控件時的驗證功能及其驗證表達式介紹如下:

只能輸入數字:“^[0-9]*$”
只能輸入n位的數字:“^d{n}$”
只能輸入至少n位數字:“^d{n,}$”
只能輸入m-n位的數字:“^d{m,n}$”
只能輸入零和非零開頭的數字:“^(0|[1-9][0-9]*)$”
只能輸入有兩位小數的正實數:“^[0-9]+(.[0-9]{2})?$”
只能輸入有1-3位小數的正實數:“^[0-9]+(.[0-9]{1,3})?$”
只能輸入非零的正整數:“^+?[1-9][0-9]*$”
只能輸入非零的負整數:“^-[1-9][0-9]*$”
只能輸入長度為3的字符:“^.{3}$”
只能輸入由26個英文字母組成的字符串:“^[A-Za-z]+$”
只能輸入由26個大寫英文字母組成的字符串:“^[A-Z]+$”
只能輸入由26個小寫英文字母組成的字符串:“^[a-z]+$”
只能輸入由數字和26個英文字母組成的字符串:“^[A-Za-z0-9]+$”
只能輸入由數字、26個英文字母或者下劃線組成的字符串:“^w+$”
驗證用戶密碼:“^[a-zA-Z]w{5,17}$”正確格式為:以字母開頭,長度在6-18之間,

只能包含字符、數字和下劃線。
驗證是否含有^%&',;=?$"等字符:“[^%&',;=?$x22]+”
只能輸入漢字:“^[u4e00-u9fa5],{0,}$”
驗證Email地址:“^w+[-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*$”
驗證InternetURL:“^http://([w-]+.)+[w-]+(/[w-./?%&=]*)?$”
驗證電話號碼:“^((d{3,4})|d{3,4}-)?d{7,8}$”

正確格式為:“XXXX-XXXXXXX”,“XXXX-XXXXXXXX”,“XXX-XXXXXXX”,

“XXX-XXXXXXXX”,“XXXXXXX”,“XXXXXXXX”。
驗證身份證號(15位或18位數字):“^d{15}|d{}18$”
驗證一年的12個月:“^(0?[1-9]|1[0-2])$”正確格式為:“01”-“09”和“1”“12”
驗證一個月的31天:“^((0?[1-9])|((1|2)[0-9])|30|31)$”

正確格式為:“01”“09”和“1”“31”。

匹配中文字符的正則表達式: [u4e00-u9fa5]
匹配雙字節字符(包括漢字在內):[^x00-xff]
匹配空行的正則表達式:n[s| ]*r
匹配HTML標記的正則表達式:/<(.*)>.*
|<(.*) />/
匹配首尾空格的正則表達式:(^s*)|(s*$)
匹配Email地址的正則表達式:w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*
匹配網址URL的正則表達式:http://([w-]+.)+[w-]+(/[w- ./?%&=]*)?
(1)應用:計算字符串的長度(一個雙字節字符長度計2,ASCII字符計1)
String.prototype.len=function(){return this.replace([^x00-xff]/g,"aa").length;}
(2)應用:javascript中沒有像vbscript那樣的trim函數,我們就可以利用這個表達式來實現
String.prototype.trim = function()
{
return this.replace(/(^s*)|(s*$)/g, "");
}
(3)應用:利用正則表達式分解和轉換IP地址
function IP2V(ip) //IP地址轉換成對應數值
{
re=/(d+).(d+).(d+).(d+)/g //匹配IP地址的正則表達式
if(re.test(ip))
{
return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1
}
else
{
throw new Error("Not a valid IP address!")
}
}
(4)應用:從URL地址中提取文件名的javascript程序
s="http://www.9499.net/page1.htm";
s=s.replace(/(.*/){0,}([^.]+).*/ig,"$2") ; //Page1.htm
(5)應用:利用正則表達式限制網頁表單裡的文本框輸入內容
用 正則表達式限制只能輸入中文:onkeyup="value=value.replace(/[^u4E00-u9FA5]/g,'') " onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^u4E00-u9FA5]/g,''))"
用 正則表達式限制只能輸入全角字符: onkeyup="value=value.replace(/[^uFF00-uFFFF]/g,'') " onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^uFF00-uFFFF]/g,''))"
用 正則表達式限制只能輸入數字:onkeyup="value=value.replace(/[^d]/g,'') "onbeforepaste= "clipboardData.setData('text',clipboardData.getData('text').replace(/[^d]/g,''))"
用 正則表達式限制只能輸入數字和英文:onkeyup="value=value.replace(/[W]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^d]/g,''
資料來源
http://mengqingyu.iteye.com/blog/426454

信用卡檢查

  1. //信用卡檢查
  2. ‘/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6011[0-9]{12}|622((12[6-9]|1[3-9][0-9])|([2-8][0-9][0-9])|(9(([0-1][0-9])|(2[0-5]))))[0-9]{10}|64[4-9][0-9]{13}|65[0-9]{14}|3(?:0[0-5]|[68][0-9])[0-9]{11}|3[47][0-9]{13})*$/’

檢查字串只能有文字與數字

  1. //檢查字串只能有文字與數字
  2. ‘/^[a-zA-Z0-9]*$/’

檢查字串只能有文字

  1. //檢查字串只能有文字
  2.  ‘/^[a-zA-Z]*$/’

檢查字串只能有小寫字母

  1. //檢查字串只能有數字
  2. ‘/^[0-9]*$/’

檢查日期型態 (MM/DD/YYYY)

  1. //檢查日期型態 (MM/DD/YYYY)
  2. ‘/^((0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])[- /.](19|20)?[0-9]{2})*$/’

檢查日期型態 (YYYY/MM/DD)

  1. //檢查日期型態 (YYYY/MM/DD)
  2.  ‘#^((19|20)?[0-9]{2}[- /.](0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01]))*$#’

簡易的Email檢查

  1. //簡易的Email檢查
  2. ‘/^([a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})*$/’

檢查IP位址

  1. //檢查IP位址
  2. ‘/^((?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))*$/’

檢查密碼:密碼長度必須有八碼,並且包含至少一個小寫字母與一個大寫字母和一個數字

  1. //檢查密碼
  2.  ‘/^(?=^.{8,}$)((?=.*[A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z]))^.*$/’

檢查網址

  1. //檢查網址
  2. ‘/^(((http|https|ftp):\/\/)?([[a-zA-Z0-9]\-\.])+(\.)([[a-zA-Z0-9]]){2,4}([[a-zA-Z0-9]\/+=%&_\.~?\-]*))*$/’
資料來源
http://lab.hsdn.net/blog/2009/09/%E5%B8%B8%E7%94%A8%E7%9A%84%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%A4%BA%E5%BC%8Fregular-expression/


一些正則表達式的學習
http://blog.roodo.com/rocksaying/archives/2670695.html
http://neural.cs.nthu.edu.tw/jang/books/javascript/regExp03.asp?title=9-3%20%E9%80%9A%E7%94%A8%E5%BC%8F%E7%9B%B8%E9%97%9C%E5%88%97%E8%A1%A8\\

其他參考
http://s.yanghao.org/program/viewdetail.php?i=268190
http://www.csharpwin.com/csharpspace/9442r8768.shtml
http://renjin.blogspot.tw/2008/08/regular-expression-examples.html