高級Oracle DBA,善長Linux系統維運以及Oracle數據庫管理,開發,調優. 具有多年PL/SQL開發經驗.
分类:
2007-03-09 09:26:13
Regex學習日記
第二章:
計數用法,記憶功能.或運算
-------------------------------------------------------------------------
1 .定位:
某符號具有 「定位」 功能, 但本身不吃掉任何字元的 :
^... 以 ... 開頭的字串
...$ 以 ... 結尾的字串
\b 文數字/非文數字 的邊界。
/^Hello$/ :這句是表示字串是Hello,H為第一個字母,o為最後一個字母.
/\bOrder\b/ :表示字串包含Order這個單詞,但是Orders會忽略.
2. 現在我們來回顧前一章的最後的問題, 寫出日期的正則表達式, 日期顯示方式有yyyy-mm-dd,
yyyy/mm/dd 兩種,那麼正則表達式該是這樣子,
/[0-9][0-9][0-9][0-9][-\/][0-9][0-9][-\/][0-9][0-9]/ ,表示1-4,6-7,9-10位都必須是數字,
5,8位可以是"-"或"/", 很是復雜, 簡化一下變成, /\d\d\d\d[-\/]\d\d[-/]\d\d/ ,很多個\d
讓人眼花撩亂,這時 我們可以用某中計數法表示,用花括號中的數字表示前面字符重複次數,如{5},{4},
那麼再簡化為 /\d{4}[-\/]\d{2}[-\/]\d{2}/
計數用法說明, 表達 「前面那個東西重複出現多少次」
{5} 重複 5 次
{3,7} 重複 3 到 7 次
? 可有可無 (0 次或 1 次)
* 重複出現任意次, 包含 0 次
+ 重複出現任意次, 至少 1 次
所謂 「前面那個東西」 可能是一個字元, 也可能是由小括弧括起來的一長串
舉例說明:
/a{10}/ 表示10個a, "aaaaaaaaaa"
/[a-z]{5}/ 表示5個字母, "abcfg","zfesz"......
/\d{2,4}/ 表示可以為2,3,4個數字.
/[a-z]*/ 表示0至n個小寫字母, "","a","abc"......
/[A-Za-z]+/ 至少一個字母,"a","aa","aaaaaaaaa"..........
/Orders?/ 表示可以為"Order",或"Orders"
3. 記憶功能.用圓括號.
以上的方法能做些什麼用途呢? 也許真的只能做字符串檢驗,判斷. 下面我提一個問題,
a. 有一行字串"Order : T004423 DEP:23234 MAT_NO : N442343243234", Order也可以是Orders,
我現在需要提取定單號和物料代號,也就是"T004423","N44234324234". 想一想,如果平常用程序該怎麼寫,
我這麼想,
1.要分析該字串同時包含Order,和MAT_NO,或Orders和MAT_NO,
2.要確定Order置於字串首,MAT_NO在其後.
3.Order,MAT_NO後帶空格加冒號.
也許我們還要知道,訂單以T開頭,長度為7,MAT_NO,以"N"開頭,長度大於10
根據所學regex,我們可以寫正則表達式
/^Orders? : T.{6}.*MAT_NO : N.{10,}$/
想一想每一段的意義,我們再用圓括號括起我們所需要的內容.那就變成了
/^Orders? : (T.{6}).*MAT_NO : (N.{10,})$/
如果用$1變量,表示括起來的第一個字串,那麼訂單號為$1,物料代號為$2 .
b. 我截取一段Oracle Listener的日志,類似如下,如果要知道用戶登錄時間,主機名稱,IP,使用的程序
是什麼?那又如何處理?
25-7月 -2005 16:54:13 * (CONNECT_DATA=(SID=orcl)(CID=(PROGRAM=)(HOST=fileshare.dg.com.cn)(USER=root))) * (ADDRESS=(PROTOCOL=tcp)(HOST=172.17.94.91)(PORT=29952)) * establish * orcl * 0
25-7月 -2005 16:54:24 * (CONNECT_DATA=(SID=ORCL)(CID=(PROGRAM=C:\PROGRAM FILES\SERVE_SYS\OTL_APP.EXE)(HOST=YYN-20137)(USER=luo))) * (ADDRESS=(PROTOCOL=tcp)(HOST=172.17.20.137)(PORT=1136)) * establish * ORCL * 0
25-7月 -2005 16:55:16 * (CONNECT_DATA=(SID=ORCL)(CID=(PROGRAM=C:\PROGRAM FILES\SERVE_SYS\OTL_APP.EXE)(HOST=YYN-2064)(USER=lucy-yy))) * (ADDRESS=(PROTOCOL=tcp)(HOST=172.17.20.64)(PORT=1401)) * establish * ORCL * 0
25-7月 -2005 16:55:18 * (CONNECT_DATA=(SERVER=DEDICATED)(SID=ORCL)(CID=(PROGRAM=C:\Program Files\Sybase\PowerBuilder 8.0\pb80.exe)(HOST=HCP)(USER=Administrator))) * (ADDRESS=(PROTOCOL=tcp)(HOST=172.17.88.220)(PORT=1735)) * establish * ORCL * 0
我用正則表達式是這麼寫的,
/(^.*) \* \(CONNECT.*PROGRAM=(.*)\)\(HOST=(.*?)\).*HOST=([\d.]*)/
然後再打印$1,$2,$3,$4 . 想一想為什麼要這麼寫呢?
c.看看字串, "aa","bb","cc","dd","eeeeeeeee",要做這種判斷又如何處理?
其實很簡單,在Regex中也可以使用記憶功能,\1,\2表示第1,2個變量.那麼表達式就是.
/(\w)\1{2,}/
4. 或運算
(?:aa|bb) aa或者是bb .前用?:表示不取其值.
m#^(?:http://|https://)?([^/]+)(.*$)#
/(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)/ 星期日至六任一日期
測試:
1. 寫出一個數字的正則表達式, (包括正負整數,小數)
2. 寫出url的正則表達式,ftp,https,().
3. 你是否覺得/\d{4}[-\/]\d{2}[-\/]\d{2}/ 表示日期是否還可以改進, 2005/01-22 這樣寫也會合法嗎?
那該如何寫?
Write :阿飛
Date : 2005-08-08