一、前言
時間匆匆流去,我已經來博客園快要兩年了,在這裡我學會了很多知識,博客園給我帶來了知識上的充實和分享的快樂!我現在要分享的是關於正則表達式的一些使用方法,在次聲明:必須有一定的正則表達式的基礎,否則會有些吃力,如果你對基礎不是很了解請翻到這章節:
淺析正則表達式-原理篇
http://www.cnblogs.com/dwlsxj/p/Regex.html
淺析正則表達式-柳暗花明又一村篇
http://www.cnblogs.com/dwlsxj/p/Reg.html
通過上面兩篇文章的講解我相信正則會有一定的基礎,並會有一定的提升,我們接下來我們就要講解本章的重點內容了,正則表達式的使用,這裡很多人都會迷茫,我那些元字符之類的我都背的很熟悉,但是就是寫不好正則表達式,不知道從哪裡下手,我相信通過這篇文章會給大家帶來一個思路,我這裡說的只是小弟的一些心得,以及這麼長時間來對正則使用的一些感悟。
二、應用篇
我們這裡不會說太多理論方面的知識,這樣看的也有些厭煩,我從實例出發,主要正則表達式還是應用於.NET平台,其他的沒有過的研究,但是這裡只是一些思想。
個人總結方法:
首先拿到原文本了解匹配的內容(這裡就是要匹配的需求)
分解組成成分,考慮采用那些正則元字符等來寫(正則分析)
根據需求思考所有出現的情況(完整性)
下面從簡單例子著手:
例子一:匹配騰訊的QQ號
我想大家對這個很了解,大家都在用QQ號,都知道QQ號的組成成分應該就是一連串的數字,OK,那麼我們這就是對原文本的內容了解,下面我們要考慮的這些數字所有出現的可能騰訊的QQ號是從10000開始也就是從10000數字進行往上增加。那麼我們就可以分解出來第一個數字不能是0開頭的,而且後面要是以4個數字以上。
這樣我們就分析出來了所有出現的可能性。我們就將正則表達式進行分解。首先我們分解的是首位字符:必須要大於0,那麼我們就采用字符類[1-9]這樣就搞定了首位字符,那麼後面還剩下四位字符,這就好辦了,後面四位字符的規則是數字0開始至少有四位那麼就可以這樣寫[0-9]{4,},這樣就表示數字從0開始9結束的任意字符至少重復4次。
正則表達式:[1-9][0-9]{4,}
原文本:10000
匹配結果如下圖所示:
例子二:匹配下面的JSON返回的對象內容,匹配所有鍵值對
原文本為:{"Dimension1":17.70,"Dimension2":16.70,"Level":"MN","Type":"LVGRM"},
{"Dimension1":9.30,"Dimension2":11.90,"Level":"MN","Type":"DINRM"},
{"Dimension1":11.20,"Dimension2":12.00,"Level":"MN","Type":"KITCH"},
{"Dimension1":12.00,"Dimension2":11.20,"Level":"MN","Type":"EATAR"},
{"Dimension1":12.20,"Dimension2":13.00,"Level":"MN","Type":"FAMRM"},
{"Dimension1":15.50,"Dimension2":13.11,"Level":"ABV","Type":"MBDRM"},
{"Dimension1":8.10,"Dimension2":6.50,"Level":"ABV","Type":"WICLO"},
{"Dimension1":12.90,"Dimension2":11.50,"Level":"ABV","Type":"BDRM"},
{"Dimension1":14.30,"Dimension2":14.10,"Level":"ABV","Type":"BDRM"},
{"Dimension1":8.90,"Dimension2":5.10,"Level":"ABV","Type":"LAUND"},
{"Dimension1":14.50,"Dimension2":28.70,"Level":"BST","Type":"RECRM"}
首先我來說明一下這個比如第一行我們是將四對鍵值對一一匹配出來,Dimension1對應的是17.70,Dimension2對應的是16.70,Level對應的是MN,Type對應的是LVGRM。這樣清楚了要匹配內容,這裡就是我們理解的要匹配的需求。這裡我們就要分析這個正則中所有出現的可能性,我們發現”Dimension1”,” Dimension2”,” Level”,” Type”這些鍵裡面有共同的特點,也就是兩邊是雙引號,中間是字符,通過分段分析之後我們可以得出前面一部分的正則表達式寫法是”[a-zA-Z0-9_]+”,注意了這樣匹配我們會將雙引號也會匹配進去,那麼我們就會想到一個東西那就是將引號裡面的內容進行分組,我們讀取出來的正則直接取出改組的內容即可(這就是考慮問題的完整性),這裡我們將前半部分的正則表達式進行完善:”([a-zA-Z0-9_]+)”,好了前半部分的完成了再繼續往下分析整個結構,後面跟了一個:那麼我們的正則後面也跟一個”([a-zA-Z0-9_]+)”:,看一下我們的分析的結果:
接下來我們就來分析下一段也就是值得內容,這裡我們看到了值分為了兩種情況:一種情況是小數,另一種情況是帶了雙引號的字符,那麼我們怎樣將這兩個組合到一起是一個關鍵,那麼我們就先來找一下他們的共同點,共同點就是他們都可以用正則的\w來進行匹配,那麼我們就用字符類將所有可能出現的結果放在字符類裡面就會出現[\w.],既然匹配的內容我們已經想辦法獲取到了,那麼我們就會想到這個雙引號可有可無,那麼我們就想到了懶惰的意思,那麼我們就可以使用懶惰來進行完善這個正則表達式:”([a-zA-Z0-9_]+)”:”?([\w.]+)”?這樣我們的正則表達式就寫好了我們來看一下結果:
附帶一張思維導圖,方便大家對上述分析的理解:
簡單的例子咱們這邊就不做分享了,有時間自己來研究下就可以了,下面我們來說一個大家都認為用不上的平衡組的例子,第一篇(原理篇)文章的第九講講到平衡組裡面有一個很明顯的案例就是說小括號匹配的問題,這裡我就不詳細說明了。接下來我們來講解一個例子。
例子三:匹配SQL語句裡面的case….when…語句
下面是原文本:convert(decimal(18,4),(case replace(f3999 ,',','') when '' then '0' else isnull(replace(f3999 ,',',''),'0') end)),
(case f2733 when 'house' then isnull(f2285,'') else isnull(f2833,'') end),
(case f2733 when 'house' then isnull(f2576,'') else isnull(f3083,'') end),
(case f2733 when 'house' then isnull(f2574,'') else isnull(f3081,'') end),
(case f2733 when 'house' then isnull(f477,'') else isnull(f96,'') end),
(case f2733 when 'house' then isnull(f714,'') else isnull(f404,'') end),
下面我們就對這個正則進行分析,首先第一點我們要明白這個裡面需求,從字面語句上去理解,看了原文本也應該清楚我們匹配的是case…when…語句,好了我們了解了我們要匹配什麼東西,那麼我們就來對正則的分析,分段進行分析,進行分析的時候我們能夠看到這裡面有很多的小括號,如果我們這樣協寫正則的話”(原文本)”用單純的兩個括號來進行匹配的話僅僅會匹配從左到右最後一次匹配的括號裡面的內容,所以這樣不是我們想要的結果,這時候我們要想一個整體的思路,這時候我們就要想到一個我們在原理篇談到的平衡組,用平衡組來進行如果碰到(就壓入堆棧,如果碰到)就彈出堆棧,最後判斷堆棧裡面內容是不是為空的。好的,廢話不多說,我們來進行更詳細的分析,我們上面已經確定了整體的思路,下面分段進行分析首先我們單獨拿出一個SQL出來 case replace(f3999 ,',','') when '' then '0' else isnull(replace(f3999 ,',',''),'0') end,通過這個語句我們可以先簡單的進行分析一下,這裡面一共有三對括號,首先要壓入堆棧的是最開始的一個括號也就是replace後面的左括號”(”,先進入堆棧中,其次他在進行向後匹配的過程中,這個左括號找到了他的伴侶右括號,就將左括號彈出堆棧,繼續往下尋找又碰到了isnull後面的左括號壓入堆棧,後面繼續往下進行匹配的過程中該左括號A(在堆棧中的)暫時沒有找到他的伴侶,卻找到了他的情敵左括號B,於是兩個左括號不服相繼被壓入堆棧中進行對抗,不料在半路中左括號B於左括號A在爭奪情人的時候,左括號B遇上了他一見鐘情的右括號B,左括號B就退出了A於B的愛情Battle,於是愛河裡面就剩下了孤零零的左括號A,獨自繼續尋找自己心愛的人,經過漫長的時間後左括號A終於找尋到了自己心愛的右括號A,兩人相伴終生,最後惡魔大人下來整治單身貴族,發現愛河裡面已經沒有單相思了,惡魔就悄然離去。整體思路就是這樣,我們進行分段講解既然這裡面的關鍵點就在於括號,那麼我們就一括號來做劃分,第一個左括號之前的內容還是比較容易的,所有組成成分中包含空格,字符兩種,這裡要拋棄掉關鍵字段左右括號,那麼我們的正則表達式①為:case [^\(\)]*,對應我們也將匹配的結果放上來:
下面我們就要進入匹配第一個左括號了,我們將這個平衡組的名稱取名為battle吧,接下來就是將左括號壓入到battle中去,正則如下:(?’battle’\()接下來就是括號裡面的內容了,經過我們的分析和詳細觀察源文本得出一個結果就是這個裡面的內容一定不包括左右括號以外的所有內容,那麼這個正則就會這樣寫[^\(\)]*,所以這兩句正則組合在一起就是(?’battle’\()[^\(\)]*,而這僅僅是愛情的開始,獨自一人在愛河中尋找真愛的人不僅僅只有他一個人,也許還會有很多,那麼我們就將這些人劃為一類人,那麼就僅僅是在數量上的增加了,後面正則會是這樣((?’battle’\()[^\(\)]*)+既然我們已經找到了左邊的括號那麼左邊的括號就不會耐得住寂寞獨自一人,他會千方百計去尋找他的另一半,那麼當他遇到右括號的時候就飛出愛的海洋於相愛的人相伴一生,那麼接下來的正則就應該是這樣遇到了右括號就將左括號彈出來,如下所示:(?’-battle’\))那麼後面跟隨的依然是除了左右括號之外的東西[^\(\)]*,最後的正則是(?’-battle’\))[^\(\)]*,前面說了既然愛河中有很多單身的人,那麼單身的人選擇的人應該也是有很多的但是自己心愛的人只有一個。最後的正則是這樣:((?’-battle’\))[^\(\)]*)+,通過左右括號比翼雙飛的結果我們可以看出他們是永遠的一對,永遠都是一起的那麼他們就應該是整體的一組成員,對他們進行整合,(((?’battle’\()[^\(\)]*)+((?’-battle’\))[^\(\)]*)+)*也許括號的出現一對都沒有,也許會有一對或更多情侶的出現,所以後面加了數量詞,既然都成雙成對了,那麼battle堆棧中就不應該出現單值出現的成員,我們要對battle堆棧進行檢驗,也就是這句正則(?(battle)(?!))最後將整體的正則進行完整性的整合就是:case[^\(\)]*(((?'battle'\()[^\(\)]*)+((?'-battle'\))[^\(\)]*)+)*(?(battle)(?!)),這樣我們的分析就完整了,下面來看一下整體匹配的結果:
簡單將堆棧變化圖進行分析:
最後將整體的思維導圖整理出來,供大家思考方便:
三、結束語
零零散散的整理了三篇正則表達式的文章,如果有哪裡不正確或者不完整的,希望能夠指正,通過這幾篇文章的總結,我相信看過這些文章的人正則有一定的提升,我自己本身的正則也有一定的提升!
標簽: 【01】正則表達式
綠色通道: 好文要頂 關注我 收藏該文與我聯系
BattleHeart
關注 - 32
粉絲 - 64
+加關注
3 0
(請您對文章做出評價)
« 上一篇:淺析MSIL中間語言——基礎篇
posted @ 2014-10-09 16:26 BattleHeart 閱讀(229) 評論(4) 編輯 收藏
評論列表
#1樓 2014-10-09 16:45 小顛
高端大氣上檔次,低調奢華有內涵呀
支持(1)反對(0)
#2樓 2014-10-09 21:00 plp913774234
必須贊,贊!贊!贊!
支持(1)反對(0)
#3樓 2014-10-09 22:28 范林軍
支持樓主,大贊
支持(0)反對(0)
#4樓 2014-10-10 00:10 光腳丫思考
後面繼續往下進行匹配的過程中該左括號A(在堆棧中的)暫時沒有找到他的伴侶,卻找到了他的情敵左括號B,於是兩個左括號不服相繼被壓入堆棧中進行對抗,不料在半路中左括號B於左括號A在爭奪情人的時候,左括號B遇上了他一見鐘情的右括號B,左括號B就退出了A於B的愛情Battle,於是愛河裡面就剩下了孤零零的左括號A,獨自繼續尋找自己心愛的人,經過漫長的時間後左括號A終於找尋到了自己心愛的右括號A,兩人相伴終生,最後惡魔大人下來整治單身貴族,發現愛河裡面已經沒有單相思了,惡魔就悄然離去。