?? 正則表達式30分鐘入門教程.htm
字號:
<TD>Multiline(多行模式)</TD>
<TD>更改<SPAN class=code>^</SPAN>和<SPAN
class=code>$</SPAN>的含義,使它們分別在任意一行的行首和行尾匹配,而不僅僅在整個字符串的開頭和結尾匹配。(在此模式下,<SPAN
class=code>$</SPAN>的精確含意是:匹配\n之前的位置以及字符串結束前的位置.) </TD></TR>
<TR>
<TD>Singleline(單行模式)</TD>
<TD>更改<SPAN class=code>.</SPAN>的含義,使它與每一個字符匹配(包括換行符\n)。 </TD></TR>
<TR>
<TD>IgnorePatternWhitespace(忽略空白)</TD>
<TD>忽略表達式中的非轉義空白并啟用由<SPAN class=code>#</SPAN>標記的注釋。</TD></TR>
<TR>
<TD>RightToLeft(從右向左查找)</TD>
<TD>匹配從右向左而不是從左向右進行。</TD></TR>
<TR>
<TD>ExplicitCapture(顯式捕獲)</TD>
<TD>僅捕獲已被顯式命名的組。</TD></TR>
<TR>
<TD>ECMAScript(JavaScript兼容模式)</TD>
<TD>使表達式的行為與它在JavaScript里的行為一致。</TD></TR></TBODY></TABLE>
<P>一個經常被問到的問題是:是不是只能同時使用多行模式和單行模式中的一種?答案是:不是。這兩個選項之間沒有任何關系,除了它們的名字比較相似(以至于讓人感到疑惑)以外。</P>
<H2 id=balancedgroup>平衡組/遞歸匹配</H2>
<P class=important>注意:這里介紹的平衡組語法是由.Net
Framework支持的;其它語言/庫不一定支持這種功能,或者支持此功能但需要使用不同的語法。 </P>
<P>有時我們需要匹配像<SPAN class=desc>( 100 * ( 50 + 15 )
)這樣的可嵌套的層次性結構</SPAN>,這時簡單地使用<SPAN
class=code>\(.+\)</SPAN>則只會匹配到最左邊的左括號和最右邊的右括號之間的內容(這里我們討論的是貪婪模式,懶惰模式也有下面的問題)。假如原來的字符串里的左括號和右括號出現的次數不相等,比如<SPAN
class=string>( 5 / ( 3 + 2 ) )
)</SPAN>,那我們的匹配結果里兩者的個數也不會相等。有沒有辦法在這樣的字符串里匹配到最長的,配對的括號之間的內容呢? </P>
<P>為了避免<SPAN class=code>(</SPAN>和<SPAN
class=code>\(</SPAN>把你的大腦徹底搞糊涂,我們還是用尖括號代替圓括號吧。現在我們的問題變成了如何把<SPAN class=string>xx
<aa <bbb> <bbb> aa> yy</SPAN>這樣的字符串里,最長的配對的尖括號內的內容捕獲出來? </P>
<P>這里需要用到以下的語法構造:</P>
<UL>
<LI><SPAN class=code>(?'group')</SPAN> 把捕獲的內容命名為group,并壓入堆棧
<LI><SPAN class=code>(?'-group')</SPAN>
從堆棧上彈出最后壓入堆棧的名為group的捕獲內容,如果堆棧本來為空,則本分組的匹配失敗
<LI><SPAN class=code>(?(group)yes|no)</SPAN>
如果堆棧上存在以名為group的捕獲內容的話,繼續匹配yes部分的表達式,否則繼續匹配no部分
<LI><SPAN class=code>(?!)</SPAN> 零寬負向先行斷言,由于沒有后綴表達式,試圖匹配總是失敗 </LI></UL>
<P>如果你不是一個程序員(或者你是一個對堆棧的概念不熟的程序員),你就這樣理解上面的三種語法吧:第一個就是在黑板上寫一個
"group",第二個就是從黑板上擦掉一個"group",第三個就是看黑板上寫的還有沒有"group",如果有就繼續匹配yes部分,否則就匹配
no部分。</P>
<P>我們需要做的是每碰到了左括號,就在黑板上寫一個"group",每碰到一個右括號,就擦掉一個,到了最后就看看黑板上還有沒有--如果有那就證明左括號比右括號多,那匹配就應該失敗。
</P><PRE class=regex>< #最外層的左括號
[^<>]* #最外層的左括號后面的不是括號的內容
(
(
(?'Open'<) #碰到了左括號,在黑板上寫一個"Open"
[^<>]* #匹配左括號后面的不是括號的內容
)+
(
(?'-Open'>) #碰到了右括號,擦掉一個"Open"
[^<>]* #匹配右括號后面不是括號的內容
)+
)*
(?(Open)(?!)) #在遇到最外層的右括號前面,判斷黑板上還有沒有沒擦掉的"Open";如果還有,則匹配失敗
> #最外層的右括號</PRE>
<P>平衡組的一個最常見的應用就是匹配HTML,下面這個例子可以匹配<SPAN class=desc>嵌套的<div>標簽</SPAN>:<SPAN
class=regex><div[^>]*>[^<>]*(((?'Open'<div[^>]*>)[^<>]*)+((?'-Open'</div>)[^<>]*)+)*(?(Open)(?!))</div></SPAN>.</P>
<H2 id=more>還有些什么東西沒提到</H2>
<P>我已經描述了構造正則表達式的大量元素,還有一些我沒有提到的東西。下面是未提到的元素的列表,包含語法和簡單的說明。你可以在網上找到更詳細的參考資料來學習它們--當你需要用到它們的時候。如果你安裝了MSDN
Library,你也可以在里面找到關于.net下正則表達式詳細的文檔。</P>
<TABLE cellSpacing=0>
<CAPTION>表7.尚未詳細討論的語法</CAPTION>
<TBODY>
<TR>
<TD><SPAN class=code>\a</SPAN></TD>
<TD><SPAN class=desc>報警字符(打印它的效果是電腦嘀一聲)</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>\b</SPAN></TD>
<TD><SPAN class=desc>通常是單詞分界位置,但如果在字符類里使用代表退格</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>\t</SPAN></TD>
<TD><SPAN class=desc>制表符,Tab</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>\r</SPAN></TD>
<TD><SPAN class=desc>回車</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>\v</SPAN></TD>
<TD><SPAN class=desc>豎向制表符</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>\f</SPAN></TD>
<TD><SPAN class=desc>換頁符</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>\n</SPAN></TD>
<TD><SPAN class=desc>換行符</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>\e</SPAN></TD>
<TD><SPAN class=desc>Escape</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>\0nn</SPAN></TD>
<TD><SPAN class=desc>ASCII代碼中八進制代碼為nn的字符</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>\xnn</SPAN></TD>
<TD><SPAN class=desc>ASCII代碼中十六進制代碼為nn的字符</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>\unnnn</SPAN></TD>
<TD><SPAN class=desc>Unicode代碼中十六進制代碼為nnnn的字符</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>\cN</SPAN></TD>
<TD><SPAN class=desc>ASCII控制字符。比如\cC代表Ctrl+C</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>\A</SPAN></TD>
<TD><SPAN class=desc>字符串開頭(類似^,但不受處理多行選項的影響)</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>\Z</SPAN></TD>
<TD><SPAN class=desc>字符串結尾或行尾(不受處理多行選項的影響)</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>\z</SPAN></TD>
<TD><SPAN class=desc>字符串結尾(類似$,但不受處理多行選項的影響)</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>\G</SPAN></TD>
<TD><SPAN class=desc>當前搜索的開頭</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>\p{name}</SPAN></TD>
<TD><SPAN class=desc>Unicode中命名為name的字符類,例如\p{IsGreek}</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>(?>exp)</SPAN></TD>
<TD><SPAN class=desc>貪婪子表達式</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>(?<x>-<y>exp)</SPAN></TD>
<TD><SPAN class=desc>平衡組</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>(?im-nsx:exp)</SPAN></TD>
<TD><SPAN class=desc>在子表達式exp中改變處理選項</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>(?im-nsx)</SPAN></TD>
<TD><SPAN class=desc>為表達式后面的部分改變處理選項</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>(?(exp)yes|no)</SPAN></TD>
<TD><SPAN
class=desc>把exp當作零寬正向先行斷言,如果在這個位置能匹配,使用yes作為此組的表達式;否則使用no</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>(?(exp)yes)</SPAN></TD>
<TD><SPAN class=desc>同上,只是使用空表達式作為no</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>(?(name)yes|no)</SPAN></TD>
<TD><SPAN class=desc>如果命名為name的組捕獲到了內容,使用yes作為表達式;否則使用no</SPAN></TD></TR>
<TR>
<TD><SPAN class=code>(?(name)yes)</SPAN></TD>
<TD><SPAN class=desc>同上,只是使用空表達式作為no</SPAN></TD></TR></TBODY></TABLE>
<H2 id=contact>聯系作者</H2>
<P>好吧,我承認,我騙了你,讀到這里你肯定花了不止30分鐘.相信我,這是我的錯,而不是因為你太笨.我之所以說"30分鐘",是為了讓你有信心,有耐心繼續下去.既然你看到了這里,那證明我的陰謀成功了.上這種當的滋味還不錯吧?</P>
<P>要投訴我,或者覺得我其實可以做得更好,或者有任何其它問題,歡迎來<A
href="http://www.cnblogs.com/deerchao/archive/2006/08/24/zhengzhe30fengzhongjiaocheng.html">我的博客</A>進行討論.</P>
<H2 id=reference>一些我認為你可能已經知道的術語的參考</H2>
<DL>
<DT>字符
<DD>程序處理文字時最基本的單位,可能是字母,數字,標點符號,空格,換行符,漢字等等。
<DT>字符串
<DD>0個或更多個字符的序列。
<DT>文本
<DD>文字,字符串。
<DT>匹配
<DD>符合規則,檢驗是否符合規則,符合規則的部分。
<DT>斷言
<DD>聲明一個應該為真的事實。只有當斷言為真時才會對正則表達式繼續進行匹配。 </DD></DL>
<H2 id=resources>網上的資源及本文參考文獻</H2>
<UL>
<LI><A
href="http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/jscript7/html/jsreconintroductiontoregularexpressions.asp">微軟的正則表達式教程</A>
<LI><A
href="http://msdn2.microsoft.com/zh-cn/library/system.text.regularexpressions.regex.aspx">System.Text.RegularExpressions.Regex類(MSDN)</A>
<LI><A href="http://www.regular-expressions.info/">專業的正則表達式教學網站(英文)</A>
<LI><A
href="http://weblogs.asp.net/whaggard/archive/2005/02/20/377025.aspx">關于.Net下的平衡組的詳細討論(英文)</A>
<LI><A href="http://www.oreilly.com/catalog/regex2/">Mastering Regular
Expressions (Second Edition)</A>
<LI><A href="http://validator.w3.org/check?uri=referer">Validated XHTML 1.0
Strict</A>
<LI><A href="http://jigsaw.w3.org/css-validator/check/referer">Validated CSS
2.1</A>
<LI><A href="http://www.mozilla.com/">推薦使用Mozilla FireFox瀏覽</A> </LI></UL>
<H2 id=updatelog>更新說明</H2>
<OL>
<LI>2006-3-27 第一版
<LI>2006-10-12 第二版
<UL>
<LI>修正了幾個細節上的錯誤和不準確的地方
<LI>增加了對處理中文時的一些說明
<LI>更改了幾個術語的翻譯(采用了MSDN的翻譯方式)
<LI>增加了平衡組的介紹
<LI>放棄了對The Regulator的介紹,改用Regex Tester </LI></UL>
<LI>2007-3-12 V2.1
<UL>
<LI>修正了幾個小的錯誤
<LI>增加了對處理選項(RegexOptions)的介紹 </LI></UL>
<LI>2007-5-28 V2.2
<UL>
<LI>重新組織了對零寬斷言的介紹
<LI>刪除了幾個不太合適的示例,添加了幾個實用的示例
<LI>其它一些微小的更改 </LI></UL>
<LI>2007-8-3 V2.21
<UL>
<LI>修改了幾處文字錯誤
<LI>修改/添加了對$,\b的精確說明
<LI>承認了作者是個騙子
<LI>給RegexTester添加了Singleline選項的相關功能 </LI></UL></LI></OL></BODY></HTML>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -