從制造到創造
          軟件工程師成長之路
          posts - 292,  comments - 96,  trackbacks - 0
          1、使用觸發器
          2、開發動態sql
          3、Using SET Operators.
          4、處理例外
          5、開發包
          6、開發子過程
          7、折紙
          8、Spring的任務調度服務實例講解 {轉}
          9、JNDI配置原理詳解
          10、我與公司共成長
          11、[翻譯] 如何在 JavaScript 中實現拖放(上)
          12、JAVA基礎(一):多態(overloading & overridding)的分析
          13、Log4j全面剖析
          14、js基礎
          15、JAVA程序員面試32問
          16、windows一些快捷鍵
          17、一道算法題
          18、怎樣對電子商務系統進行運營評估
          19、js常用函數
          20、【搜索】步入全文檢索第一步
          21、Java 關于中文亂碼問題的解決方案與經驗
          22、java的30個學習目標
          23、在應用中加入全文檢索功能——基于Java的全文索引引擎Lucene簡介
          24、hibernate annotations試用
          25、在RubyOnRails里使用UTF-8及中文字符串
          26、Jar命令與Jar文件
          27、Spring MVC framework深入分析之一--總體分析
          28、Spring源碼學習 - Spring 初始化之旅
          29、簡化Java應用程序的打包和發布
          30、大家來試試運氣啊...歡迎給出縮減版本
          31、java打包詳解
          32、在HQL中繞過中文亂碼查詢
          33、Eclipse 插件介紹
          34、一個有關頁保存的問題(原創)
          35、軟件測試
          36、一個學習Oracle sql 的不錯的地方,記錄一下
          37、關于java的反射機制的一些實用代碼
          38、經驗分享交流:常用SQL語句技法
          39、JAVA基礎(二):函數執行順序(構造函數,多態,this指針)
          40、ruby on rails之旅
          41、vista精神之 --javascript篇
          42、更改生物鐘的危害
          43、[轉]一個老工程師給年輕工程師的十大忠告!
          44、Socket基本編程(轉)
          45、Java MD5加密法
          46、Base64加密算法
          47、用java訪問windows注冊表
          48、JNI入門介紹
          49、中國程序員的26種能力
          50、程序員修煉之道
          51、對"類"和"對象"的深度揣摩與思考...(java初學者)
          52、棧和隊的應用-魔王語言解釋
          53、Java web 開發必游之路-給入門者的一些建議
          54、正則表達式
          55、由一個類創建多個對象時,各個對象的屬性是相互無關的,(l例題為轉載)
          56、我碰到的 ResultSet 用盡問題
          57、對方法的深入思考,(java初學者)
          58、我對"對象"和"引用"的理解(此文特指在創建一個類對象實例的情況)
          59、對類和方法的理解更正,,
          60、算法求解
          61、Hibernate 能夠滿足我們的驗證需求
          62、Cross Site AJAX [轉載]
          63、[zt]JdbcTemplate使用指南
          64、構建項目公共輔助類__CommonUtils(持續更新)
          65、《如何讓你的程序運行的更快》系列文章(持續更新)
          66、兩種不同指針的理解
          67、java基礎:字符串分割的兩種方法
          68、ANT 基本使用教程
          69、在線網頁編輯器大全
          70、好玩的js~~~
          71、magic Javascript
          72、mysql入門1
          73、EasyDBO最后一個測試版(0.9.0)發布
          74、匯豐面試記(轉)
          75、mysql入門2
          76、閻宏博士的JAVA與模式
          77、inconstant constants(變化無常的常量)
          78、一條sql語句刪除表中所有除ID 不同之外的記錄,只留一條。
          79、軟件高手是這樣練成的 —— 座右帖 (感覺太好了,轉載過來)
          80、Struts中使用Cookie控制登錄的流程
          81、你想到了什么?
          82、AjaxOpenDoc源代碼下載
          83、我的設計模式之旅(1)——學習的原則和一些筆記
          84、使用façade、template pattern搭建MVC框架
          85、[原創] 一個完善的輕量級分頁API Pager ! 有源代碼.......
          86、說一說編程惡習
          87、序篇
          88、Jdk1.4 和jdk1.5中的StringBuffer的不同
          89、oracle時間模糊查詢
          90、JTable 的編輯和表現
          91、Swing 的MVC
          92、Swing是MVC設計的典范(轉載)
          93、如何管理工作計劃和日志
          94、[原創]一個精巧的層控制工具 LayerUtil ....希望能滿足大家的基本需求 [Javascript]
          95、google筆試的敗筆(大家來仁者見仁哦)
          96、常用的Struts 2.0的標志(Tag)介紹
          97、JavaScript中的Email驗證
          98、經典SQL語句集錦(收藏版)
          99、如何將字符串或者數字轉換成大寫貨幣
          100、利用ajax實現實施刷新
          101、Tomcat簡介
          102、【分享】Hibernate視頻分享
          103、UML入門知識(來自軟件工程組織)
          104、Ant: 入門-配置和使用
          105、Ant: 中文教程一
          106、Ant: 中文教程
          107、Ant: 中文教程二
          posted @ 2006-10-18 22:17 CoderDream 閱讀(225) | 評論 (0)編輯 收藏
          1、SHTML 教程
          2、CSS十大密技
          posted @ 2006-10-15 11:01 CoderDream 閱讀(197) | 評論 (0)編輯 收藏
          1、深入淺出之正則表達式(一)
          2、深入淺出之正則表達式(二)
          3、Java正則表達式詳解
          4、PHP和正則表達式

          posted @ 2006-10-14 00:31 CoderDream 閱讀(245) | 評論 (0)編輯 收藏

          關鍵字: 正則表達式,Regular Expression

          作者:笑容

          發表于:2004年05月03日
          最后更新:2005年01月17日 19:54
          版權聲明:使用
          創作公用版權協議


          前言

          正則表達式是煩瑣的,但是強大的,學會之后的應用會讓你除了提高效率外,會給你帶來絕對的成就感。只要認真去閱讀這些資料,加上應用的時候進行一定的參考,掌握正則表達式不是問題。

          索引

          1._引子
          2._正則表達式的歷史
          3._正則表達式定義

          3.1_普通字符
          3.2_非打印字符
          3.3_特殊字符
          3.4_限定符
          3.5_定位符
          3.6_選擇
          3.7_后向引用

          4._各種操作符的運算優先級
          5._全部符號解釋
          6._部分例子
          7._正則表達式匹配規則

          7.1_基本模式匹配
          7.2_字符簇
          7.3_確定重復出現


          1. 引子

            目前,正則表達式已經在很多軟件中得到廣泛的應用,包括*nix(Linux, Unix等),HP等操作系統,PHP,C#,Java等開發環境,以及很多的應用軟件中,都可以看到正則表達式的影子。

            正則表達式的使用,可以通過簡單的辦法來實現強大的功能。為了簡單有效而又不失強大,造成了正則表達式代碼的難度較大,學習起來也不是很容易,所以需要付出一些努力才行,入門之后參照一定的參考,使用起來還是比較簡單有效的。

          例子: ^.+@.+\\..+$

            這樣的代碼曾經多次把我自己給嚇退過。可能很多人也是被這樣的代碼給嚇跑的吧。繼續閱讀本文將讓你也可以自由應用這樣的代碼。

            注意:這里的第7部分跟前面的內容看起來似乎有些重復,目的是把前面表格里的部分重新描述了一次,目的是讓這些內容更容易理解。

          2. 正則表達式的歷史

            正則表達式的“祖先”可以一直上溯至對人類神經系統如何工作的早期研究。Warren McCulloch 和 Walter Pitts 這兩位神經生理學家研究出一種數學方式來描述這些神經網絡。

            1956 年, 一位叫 Stephen Kleene 的數學家在 McCulloch 和 Pitts 早期工作的基礎上,發表了一篇標題為“神經網事件的表示法”的論文,引入了正則表達式的概念。正則表達式就是用來描述他稱為“正則集的代數”的表達式,因此采用“正則表達式”這個術語。

            隨后,發現可以將這一工作應用于使用 Ken Thompson 的計算搜索算法的一些早期研究,Ken Thompson 是 Unix 的主要發明人。正則表達式的第一個實用應用程序就是 Unix 中的 qed 編輯器。

            如他們所說,剩下的就是眾所周知的歷史了。從那時起直至現在正則表達式都是基于文本的編輯器和搜索工具中的一個重要部分。

           

          3. 正則表達式定義

            正則表達式(regular expression)描述了一種字符串匹配的模式,可以用來檢查一個串是否含有某種子串、將匹配的子串做替換或者從某個串中取出符合某個條件的子串等。

          • 列目錄時, dir *.txt或ls *.txt中的*.txt就 是一個正則表達式,因為這里*與正則式的*的含義是不同的。

            正則表達式是由普通字符(例如字符 a 到 z)以及特殊字符(稱為元字符)組成的文字模式。正則表達式作為一個模板,將某個字符模式與所搜索的字符串進行匹配。

          3.1 普通字符

            由所有那些未顯式指定為元字符的打印和非打印字符組成。這包括所有的大寫和小寫字母字符,所有數字,所有標點符號以及一些符號。

          3.2 非打印字符

          字符 含義
          \cx 匹配由x指明的控制字符。例如, \cM 匹配一個 Control-M 或回車符。x 的值必須為 A-Z 或 a-z 之一。否則,將 c 視為一個原義的 'c' 字符。
          \f 匹配一個換頁符。等價于 \x0c 和 \cL。
          \n 匹配一個換行符。等價于 \x0a 和 \cJ。
          \r 匹配一個回車符。等價于 \x0d 和 \cM。
          \s 匹配任何空白字符,包括空格、制表符、換頁符等等。等價于 [ \f\n\r\t\v]。
          \S 匹配任何非空白字符。等價于 [^ \f\n\r\t\v]。
          \t 匹配一個制表符。等價于 \x09 和 \cI。
          \v 匹配一個垂直制表符。等價于 \x0b 和 \cK。

           

          3.3 特殊字符

            所謂特殊字符,就是一些有特殊含義的字符,如上面說的"*.txt"中的*,簡單的說就是表示任何字符串的意思。如果要查找文件名中有*的文件,則需要對*進行轉義,即在其前加一個\。ls \*.txt。正則表達式有以下特殊字符。

           

          特別字符說明
          $匹配輸入字符串的結尾位置。如果設置了 RegExp 對象的 Multiline 屬性,則 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,請使用 \$。
          ( )標記一個子表達式的開始和結束位置。子表達式可以獲取供以后使用。要匹配這些字符,請使用 \( 和 \)。
          *匹配前面的子表達式零次或多次。要匹配 * 字符,請使用 \*。
          +匹配前面的子表達式一次或多次。要匹配 + 字符,請使用 \+。
          .匹配除換行符 \n之外的任何單字符。要匹配 .,請使用 \。
          [ 標記一個中括號表達式的開始。要匹配 [,請使用 \[。
          ?匹配前面的子表達式零次或一次,或指明一個非貪婪限定符。要匹配 ? 字符,請使用 \?。
          \將下一個字符標記為或特殊字符、或原義字符、或向后引用、或八進制轉義符。例如, 'n' 匹配字符 'n'。'\n' 匹配換行符。序列 '\\' 匹配 "\",而 '\(' 則匹配 "("。
          ^匹配輸入字符串的開始位置,除非在方括號表達式中使用,此時它表示不接受該字符集合。要匹配 ^ 字符本身,請使用 \^。
          {標記限定符表達式的開始。要匹配 {,請使用 \{。
          |指明兩項之間的一個選擇。要匹配 |,請使用 \|。
          •   構造正則表達式的方法和創建數學表達式的方法一樣。也就是用多種元字符與操作符將小的表達式結合在一起來創建更大的表達式。正則表達式的組件可以是單個的字符、字符集合、字符范圍、字符間的選擇或者所有這些組件的任意組合。

           

          3.4 限定符

            限定符用來指定正則表達式的一個給定組件必須要出現多少次才能滿足匹配。有*或+或?或{n}或{n,}或{n,m}共6種。
          *、+和?限定符都是貪婪的,因為它們會盡可能多的匹配文字,只有在它們的后面加上一個?就可以實現非貪婪或最小匹配。
            正則表達式的限定符有:
           
          字符 描述
          * 匹配前面的子表達式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等價于{0,}。
          + 匹配前面的子表達式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價于 {1,}。
          ? 匹配前面的子表達式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等價于 {0,1}。
          {n} n 是一個非負整數。匹配確定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的兩個 o。
          {n,} n 是一個非負整數。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等價于 'o+'。'o{0,}' 則等價于 'o*'。
          {n,m} m 和 n 均為非負整數,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 將匹配 "fooooood" 中的前三個 o。'o{0,1}' 等價于 'o?'。請注意在逗號和兩個數之間不能有空格。

          3.5 定位符

            用來描述字符串或單詞的邊界,^和$分別指字符串的開始與結束,\b描述單詞的前或后邊界,\B表示非單詞邊界。不能對定位符使用限定符。

          3.6 選擇

            用圓括號將所有選擇項括起來,相鄰的選擇項之間用|分隔。但用圓括號會有一個副作用,是相關的匹配會被緩存,此時可用?:放在第一個選項前來消除這種副作用。
            其中?:是非捕獲元之一,還有兩個非捕獲元是?=和?!,這兩個還有更多的含義,前者為正向預查,在任何開始匹配圓括號內的正則表達式模式的位置來匹配搜索字符串,后者為負向預查,在任何開始不匹配該正則表達式模式的位置來匹配搜索字符串。

          3.7 后向引用

            對一個正則表達式模式或部分模式兩邊添加圓括號將導致相關匹配存儲到一個臨時緩沖區中,所捕獲的每個子匹配都按照在正則表達式模式中從左至右所遇到的內容存儲。存儲子匹配的緩沖區編號從 1 開始,連續編號直至最大 99 個子表達式。每個緩沖區都可以使用 '\n' 訪問,其中 n 為一個標識特定緩沖區的一位或兩位十進制數。
            可以使用非捕獲元字符 '?:', '?=', or '?!' 來忽略對相關匹配的保存。

          4. 各種操作符的運算優先級

            相同優先級的從左到右進行運算,不同優先級的運算先高后低。各種操作符的優先級從高到低如下:
           
          操作符 描述
          \ 轉義符
          (), (?:), (?=), [] 圓括號和方括號
          *, +, ?, {n}, {n,}, {n,m} 限定符
          ^, $, \anymetacharacter 位置和順序
          | “或”操作

          5. 全部符號解釋

          字符 描述
          \ 將下一個字符標記為一個特殊字符、或一個原義字符、或一個 向后引用、或一個八進制轉義符。例如,'n' 匹配字符 "n"。'\n' 匹配一個換行符。序列 '\\' 匹配 "\" 而 "\(" 則匹配 "("。
          ^ 匹配輸入字符串的開始位置。如果設置了 RegExp 對象的 Multiline 屬性,^ 也匹配 '\n' 或 '\r' 之后的位置。
          $ 匹配輸入字符串的結束位置。如果設置了RegExp 對象的 Multiline 屬性,$ 也匹配 '\n' 或 '\r' 之前的位置。
          * 匹配前面的子表達式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等價于{0,}。
          + 匹配前面的子表達式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價于 {1,}。
          ? 匹配前面的子表達式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等價于 {0,1}。
          {n} n 是一個非負整數。匹配確定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的兩個 o。
          {n,} n 是一個非負整數。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等價于 'o+'。'o{0,}' 則等價于 'o*'。
          {n,m} m 和 n 均為非負整數,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 將匹配 "fooooood" 中的前三個 o。'o{0,1}' 等價于 'o?'。請注意在逗號和兩個數之間不能有空格。
          ? 當該字符緊跟在任何一個其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面時,匹配模式是非貪婪的。非貪婪模式盡可能少的匹配所搜索的字符串,而默認的貪婪模式則盡可能多的匹配所搜索的字符串。例如,對于字符串 "oooo",'o+?' 將匹配單個 "o",而 'o+' 將匹配所有 'o'。
          . 匹配除 "\n" 之外的任何單個字符。要匹配包括 '\n' 在內的任何字符,請使用象 '[.\n]' 的模式。
          (pattern) 匹配 pattern 并獲取這一匹配。所獲取的匹配可以從產生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中則使用 $0…$9 屬性。要匹配圓括號字符,請使用 '\(' 或 '\)'。
          (?:pattern) 匹配 pattern 但不獲取匹配結果,也就是說這是一個非獲取匹配,不進行存儲供以后使用。這在使用 "或" 字符 (|) 來組合一個模式的各個部分是很有用。例如, 'industr(?:y|ies) 就是一個比 'industry|industries' 更簡略的表達式。
          (?=pattern) 正向預查,在任何匹配 pattern 的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以后使用。例如,'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。預查不消耗字符,也就是說,在一個匹配發生后,在最后一次匹配之后立即開始下一次匹配的搜索,而不是從包含預查的字符之后開始。
          (?!pattern) 負向預查,在任何不匹配 pattern 的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。預查不消耗字符,也就是說,在一個匹配發生后,在最后一次匹配之后立即開始下一次匹配的搜索,而不是從包含預查的字符之后開始
          x|y 匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 則匹配 "zood" 或 "food"。
          [xyz] 字符集合。匹配所包含的任意一個字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
          [^xyz] 負值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。
          [a-z] 字符范圍。匹配指定范圍內的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范圍內的任意小寫字母字符。
          [^a-z] 負值字符范圍。匹配任何不在指定范圍內的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范圍內的任意字符。
          \b 匹配一個單詞邊界,也就是指單詞和空格間的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
          \B 匹配非單詞邊界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
          \cx 匹配由 x 指明的控制字符。例如, \cM 匹配一個 Control-M 或回車符。x 的值必須為 A-Z 或 a-z 之一。否則,將 c 視為一個原義的 'c' 字符。
          \d 匹配一個數字字符。等價于 [0-9]。
          \D 匹配一個非數字字符。等價于 [^0-9]。
          \f 匹配一個換頁符。等價于 \x0c 和 \cL。
          \n 匹配一個換行符。等價于 \x0a 和 \cJ。
          \r 匹配一個回車符。等價于 \x0d 和 \cM。
          \s 匹配任何空白字符,包括空格、制表符、換頁符等等。等價于 [ \f\n\r\t\v]。
          \S 匹配任何非空白字符。等價于 [^ \f\n\r\t\v]。
          \t 匹配一個制表符。等價于 \x09 和 \cI。
          \v 匹配一個垂直制表符。等價于 \x0b 和 \cK。
          \w 匹配包括下劃線的任何單詞字符。等價于'[A-Za-z0-9_]'。
          \W 匹配任何非單詞字符。等價于 '[^A-Za-z0-9_]'。
          \xn 匹配 n,其中 n 為十六進制轉義值。十六進制轉義值必須為確定的兩個數字長。例如,'\x41' 匹配 "A"。'\x041' 則等價于 '\x04' & "1"。正則表達式中可以使用 ASCII 編碼。.
          \num 匹配 num,其中 num 是一個正整數。對所獲取的匹配的引用。例如,'(.)\1' 匹配兩個連續的相同字符。
          \n 標識一個八進制轉義值或一個向后引用。如果 \n 之前至少 n 個獲取的子表達式,則 n 為向后引用。否則,如果 n 為八進制數字 (0-7),則 n 為一個八進制轉義值。
          \nm 標識一個八進制轉義值或一個向后引用。如果 \nm 之前至少有 nm 個獲得子表達式,則 nm 為向后引用。如果 \nm 之前至少有 n 個獲取,則 n 為一個后跟文字 m 的向后引用。如果前面的條件都不滿足,若 n 和 m 均為八進制數字 (0-7),則 \nm 將匹配八進制轉義值 nm。
          \nml 如果 n 為八進制數字 (0-3),且 m 和 l 均為八進制數字 (0-7),則匹配八進制轉義值 nml。
          \un 匹配 n,其中 n 是一個用四個十六進制數字表示的 Unicode 字符。例如, \u00A9 匹配版權符號 (?)。

           

          6. 部分例子

          正則表達式說明
          /\b([a-z]+) \1\b/gi一個單詞連續出現的位置
          /(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/ 將一個URL解析為協議、域、端口及相對路徑
          /^(?:Chapter|Section) [1-9][0-9]{0,1}$/定位章節的位置
          /[-a-z]/A至z共26個字母再加一個-號。
          /ter\b/可匹配chapter,而不能terminal
          /\Bapt/可匹配chapter,而不能aptitude
          /Windows(?=95 |98 |NT )/可匹配Windows95或Windows98或WindowsNT,當找到一個匹配后,從Windows后面開始進行下一次的檢索匹配。

           

          7. 正則表達式匹配規則

          7.1 基本模式匹配

            一切從最基本的開始。模式,是正規表達式最基本的元素,它們是一組描述字符串特征的字符。模式可以很簡單,由普通的字符串組成,也可以非常復雜,往往用特殊的字符表示一個范圍內的字符、重復出現,或表示上下文。例如:

          ^once

            這個模式包含一個特殊的字符^,表示該模式只匹配那些以once開頭的字符串。例如該模式與字符串"once upon a time"匹配,與"There once was a man from NewYork"不匹配。正如如^符號表示開頭一樣,$符號用來匹配那些以給定模式結尾的字符串。

          bucket$

            這個模式與"Who kept all of this cash in a bucket"匹配,與"buckets"不匹配。字符^和$同時使用時,表示精確匹配(字符串與模式一樣)。例如:

          ^bucket$

            只匹配字符串"bucket"。如果一個模式不包括^和$,那么它與任何包含該模式的字符串匹配。例如:模式

          once

          與字符串

          There once was a man from NewYork
          Who kept all of his cash in a bucket.

          是匹配的。

            在該模式中的字母(o-n-c-e)是字面的字符,也就是說,他們表示該字母本身,數字也是一樣的。其他一些稍微復雜的字符,如標點符號和白字符(空格、制表符等),要用到轉義序列。所有的轉義序列都用反斜杠(\)打頭。制表符的轉義序列是:\t。所以如果我們要檢測一個字符串是否以制表符開頭,可以用這個模式:

          ^\t

          類似的,用\n表示“新行”,\r表示回車。其他的特殊符號,可以用在前面加上反斜杠,如反斜杠本身用\\表示,句號.用\.表示,以此類推。

          7.2 字符簇

          在INTERNET的程序中,正規表達式通常用來驗證用戶的輸入。當用戶提交一個FORM以后,要判斷輸入的電話號碼、地址、EMAIL地址、信用卡號碼等是否有效,用普通的基于字面的字符是不夠的。

          所以要用一種更自由的描述我們要的模式的辦法,它就是字符簇。要建立一個表示所有元音字符的字符簇,就把所有的元音字符放在一個方括號里:

          [AaEeIiOoUu]

          這個模式與任何元音字符匹配,但只能表示一個字符。用連字號可以表示一個字符的范圍,如:

          [a-z] //匹配所有的小寫字母
          [A-Z] //匹配所有的大寫字母
          [a-zA-Z] //匹配所有的字母
          [0-9] //匹配所有的數字
          [0-9\.\-] //匹配所有的數字,句號和減號
          [ \f\r\t\n] //匹配所有的白字符

          同樣的,這些也只表示一個字符,這是一個非常重要的。如果要匹配一個由一個小寫字母和一位數字組成的字符串,比如"z2"、"t6"或"g7",但不是"ab2"、"r2d3" 或"b52"的話,用這個模式:

          ^[a-z][0-9]$

          盡管[a-z]代表26個字母的范圍,但在這里它只能與第一個字符是小寫字母的字符串匹配。

          前面曾經提到^表示字符串的開頭,但它還有另外一個含義。當在一組方括號里使用^是,它表示“非”或“排除”的意思,常常用來剔除某個字符。還用前面的例子,我們要求第一個字符不能是數字:

          ^[^0-9][0-9]$

          這個模式與"&5"、"g7"及"-2"是匹配的,但與"12"、"66"是不匹配的。下面是幾個排除特定字符的例子:

          [^a-z] //除了小寫字母以外的所有字符
          [^\\\/\^] //除了(\)(/)(^)之外的所有字符
          [^\"\'] //除了雙引號(")和單引號(')之外的所有字符

          特殊字符"." (點,句號)在正規表達式中用來表示除了“新行”之外的所有字符。所以模式"^.5$"與任何兩個字符的、以數字5結尾和以其他非“新行”字符開頭的字符串匹配。模式"."可以匹配任何字符串,除了空串和只包括一個“新行”的字符串。

          PHP的正規表達式有一些內置的通用字符簇,列表如下:

          字符簇 含義
          [[:alpha:]] 任何字母
          [[:digit:]] 任何數字
          [[:alnum:]] 任何字母和數字
          [[:space:]] 任何白字符
          [[:upper:]] 任何大寫字母
          [[:lower:]] 任何小寫字母
          [[:punct:]] 任何標點符號
          [[:xdigit:]] 任何16進制的數字,相當于[0-9a-fA-F]

          7.3 確定重復出現

          到現在為止,你已經知道如何去匹配一個字母或數字,但更多的情況下,可能要匹配一個單詞或一組數字。一個單詞有若干個字母組成,一組數字有若干個單數組成。跟在字符或字符簇后面的花括號({})用來確定前面的內容的重復出現的次數。

          字符簇 含義
          ^[a-zA-Z_]$ 所有的字母和下劃線
          ^[[:alpha:]]{3}$ 所有的3個字母的單詞
          ^a$ 字母a
          ^a{4}$ aaaa
          ^a{2,4}$ aa,aaa或aaaa
          ^a{1,3}$ a,aa或aaa
          ^a{2,}$ 包含多于兩個a的字符串
          ^a{2,} 如:aardvark和aaab,但apple不行
          a{2,} 如:baad和aaa,但Nantucket不行
          \t{2} 兩個制表符
          .{2} 所有的兩個字符

          這些例子描述了花括號的三種不同的用法。一個數字,{x}的意思是“前面的字符或字符簇只出現x次”;一個數字加逗號,{x,}的意思是“前面的內容出現x或更多的次數”;兩個用逗號分隔的數字,{x,y}表示“前面的內容至少出現x次,但不超過y次”。我們可以把模式擴展到更多的單詞或數字:

          ^[a-zA-Z0-9_]{1,}$ //所有包含一個以上的字母、數字或下劃線的字符串
          ^[0-9]{1,}$ //所有的正數
          ^\-{0,1}[0-9]{1,}$ //所有的整數
          ^\-{0,1}[0-9]{0,}\.{0,1}[0-9]{0,}$ //所有的小數

          最后一個例子不太好理解,是嗎?這么看吧:與所有以一個可選的負號(\-{0,1})開頭(^)、跟著0個或更多的數字([0-9]{0,})、和一個可選的小數點(\.{0,1})再跟上0個或多個數字([0-9]{0,}),并且沒有其他任何東西($)。下面你將知道能夠使用的更為簡單的方法。

          特殊字符"?"與{0,1}是相等的,它們都代表著:“0個或1個前面的內容”或“前面的內容是可選的”。所以剛才的例子可以簡化為:

          ^\-?[0-9]{0,}\.?[0-9]{0,}$

          特殊字符"*"與{0,}是相等的,它們都代表著“0個或多個前面的內容”。最后,字符"+"與 {1,}是相等的,表示“1個或多個前面的內容”,所以上面的4個例子可以寫成:

          ^[a-zA-Z0-9_]+$ //所有包含一個以上的字母、數字或下劃線的字符串
          ^[0-9]+$ //所有的正數
          ^\-?[0-9]+$ //所有的整數
          ^\-?[0-9]*\.?[0-9]*$ //所有的小數

          當然這并不能從技術上降低正規表達式的復雜性,但可以使它們更容易閱讀。

           

          參考文獻:
          JScript?和?VBScript?正則表達式

          微軟MSDN上的例子(英文):

          Scanning for HREFS
          Provides an example that searches an input string and prints out all the href="..." values and their locations in the string.
          Changing Date Formats
          Provides an example that replaces dates of the form mm/dd/yy with dates of the form dd-mm-yy.
          Extracting URL Information
          Provides an example that extracts a protocol and port number from a string containing a URL. For example, "http://www.contoso.com:8080/letters/readme.html" returns "http:8080".
          Cleaning an Input String
          provides an example that strips invalid non-alphanumeric characters from a string.
          Confirming Valid E-Mail Format
          Provides an example that you can use to verify that a string is in valid e-mail format.
          posted @ 2006-10-14 00:25 CoderDream 閱讀(330) | 評論 (0)編輯 收藏

          ! 去除字符串兩端空格的處理

          如果采用傳統的方式,就要可能就要采用下面的方式了
          //清除左邊空格
          function js_ltrim(deststr)
          {
          ?if(deststr==null)return "";
          ?var pos=0;
          ?var retStr=new String(deststr);
          ?if (retStr.lenght==0) return retStr;
          ?while (retStr.substring(pos,pos+1)==" ") pos++;
          ?retStr=retStr.substring(pos);
          ?return(retStr);
          }
          //清除右邊空格
          function js_rtrim(deststr)
          {
          ?if(deststr==null)return "";
          ?var retStr=new String(deststr);
          ?var pos=retStr.length;
          ?if (pos==0) return retStr;
          ?while (pos && retStr.substring(pos-1,pos)==" " ) pos--;
          ?retStr=retStr.substring(0,pos);
          ?return(retStr);
          }
          //清除左邊和右邊空格
          function js_trim(deststr)
          {
          ?if(deststr==null)return "";
          ?var retStr=new String(deststr);
          ?var pos=retStr.length;
          ?if (pos==0) return retStr;
          ?retStr=js_ltrim(retStr);
          ?retStr=js_rtrim(retStr);
          ?return retStr;
          }

          采用正則表達式,來去除兩邊的空格,只需以下代碼
          String.prototype.trim = function()
          {
          return this.replace(/(^\s*)|(\s*$)/g, "");
          }

          一句就搞定了,
          可見正則表達式為我們節省了相當的編寫代碼量


          ! 移動手機號的校驗

          如果采用傳統的校驗方式至少就要完成下面三步的校驗,
          (1). 是否是數字
          (2).是否是11位
          (3).數字的第三位是否是5,6,7,8,9
          如果采用正則表達式校驗,只需以下代碼
          function checkMobile1(form)
          {
          if (form.mobile.value > "")
          {
          var reg=/13[5,6,7,8,9]\d{8}/;
          if ( form.mobile.value.match(reg)== null)
          {
          alert("請輸入正確的移動手機號碼!");
          form.mobile.focus(); return false;
          ?}
          }
          return true;
          }

          從上面的代碼可以看出校驗移動手機號只需定義一個var reg=/13[5,6,7,8,9]\d{8}/;模式匹配串就可以完成合法性校驗了

          ! URL的校驗,
          條件:必須以http:// 或 https:// 開頭, 端口號必須為在1-65535 之間, 以下代碼完成了合法性校驗

          //obj:數據對象
          //dispStr :失敗提示內容顯示字符串
          function checkUrlValid( obj,? dispStr)
          {
          ?if(obj? == null)
          ?{
          ??alert("傳入對象為空");
          ??return false;
          ?}
          ?var str = obj.value;

          ?var? urlpatern0 = /^https?:\/\/.+$/i;
          ?if(!urlpatern0.test(str))
          ?{
          ??alert(dispStr+"不合法:必須以'http:\/\/'或'https:\/\/'開頭!");
          ??obj.focus();
          ??return false;
          ?}

          ?var? urlpatern2= /^https?:\/\/(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?.+$/i;
          ?if(!urlpatern2.test(str))
          ?{
          ??alert(dispStr+"端口號必須為數字且應在1-65535之間!");
          ??obj.focus();
          ??return false;
          ?}


          ?var?urlpatern1 =/^https?:\/\/(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?(\/((\.)?(\?)?=?&?[a-zA-Z0-9_-](\?)?)*)*$/i;

          ?if(!urlpatern1.test(str))
          ?{
          ??alert(dispStr+"不合法,請檢查!");
          ??obj.focus();
          ??return false;
          ?}

          ?var s = "0";
          ?var t =0;
          ? var re = new RegExp(":\\d+","ig");
          ? while((arr = re.exec(str))!=null)
          ?{
          ??s = str.substring(RegExp.index+1,RegExp.lastIndex);

          ??if(s.substring(0,1)=="0")
          ??{
          ???alert(dispStr+"端口號不能以0開頭!");
          ???obj.focus();
          ???return false;
          ??}

          ??t = parseInt(s);
          ??if(t<1 || t >65535)
          ??{
          ???alert(dispStr+"端口號必須為數字且應在1-65535之間!");
          ???obj.focus();
          ???return false;
          ??}
          ?}
          ?return true;
          }
          ?
          對url的校驗,看上去有很多的代碼,這是因為要給予出錯提示, 否則只需var?urlpatern1 =/^https?:\/\/(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?(\/((\.)?(\?)?=?&?[a-zA-Z0-9_-](\?)?)*)*$/i; 一句就可以校驗出url合法性了。

          javascript正則表達式檢驗
          /*********************************************************************************
          * EO_JSLib.js
          * javascript正則表達式檢驗
          **********************************************************************************/

          //校驗是否全由數字組成
          function isDigit(s)
          {
          var patrn=/^[0-9]{1,20}$/;
          if (!patrn.exec(s)) return false
          return true
          }

          //校驗登錄名:只能輸入5-20個以字母開頭、可帶數字、“_”、“.”的字串
          function isRegisterUserName(s)
          {
          var patrn=/^[a-zA-Z]{1}([a-zA-Z0-9]|[._]){4,19}$/;
          if (!patrn.exec(s)) return false
          return true
          }

          //校驗用戶姓名:只能輸入1-30個以字母開頭的字串
          function isTrueName(s)
          {
          var patrn=/^[a-zA-Z]{1,30}$/;
          if (!patrn.exec(s)) return false
          return true
          }

          //校驗密碼:只能輸入6-20個字母、數字、下劃線
          function isPasswd(s)
          {
          var patrn=/^(\w){6,20}$/;
          if (!patrn.exec(s)) return false
          return true
          }

          //校驗普通電話、傳真號碼:可以“+”開頭,除數字外,可含有“-”
          function isTel(s)
          {
          //var patrn=/^[+]{0,1}(\d){1,3}[ ]?([-]?(\d){1,12})+$/;
          var patrn=/^[+]{0,1}(\d){1,3}[ ]?([-]?((\d)|[ ]){1,12})+$/;
          if (!patrn.exec(s)) return false
          return true
          }

          //校驗手機號碼:必須以數字開頭,除數字外,可含有“-”
          function isMobil(s)
          {
          var patrn=/^[+]{0,1}(\d){1,3}[ ]?([-]?((\d)|[ ]){1,12})+$/;
          if (!patrn.exec(s)) return false
          return true
          }

          //校驗郵政編碼
          function isPostalCode(s)
          {
          //var patrn=/^[a-zA-Z0-9]{3,12}$/;
          var patrn=/^[a-zA-Z0-9 ]{3,12}$/;
          if (!patrn.exec(s)) return false
          return true
          }

          //校驗搜索關鍵字
          function isSearch(s)
          {
          var patrn=/^[^`~!@#$%^&*()+=|\\\][\]\{\}:;'\,.<>/?]{1}[^`~!@$%^&()+=|\\\][\]\{\}:;'\,.<>?]{0,19}$/;
          if (!patrn.exec(s)) return false
          return true
          }

          function isIP(s) //by zergling
          {
          var patrn=/^[0-9.]{1,20}$/;
          if (!patrn.exec(s)) return false
          return true
          }

          (ip,email,data,time)

          <script language="javascript">
          ??? var patterns = new Object();

          ??? //匹配ip地址
          ??? patterns.ip = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/;

          ??? //匹配郵件地址
          ??? patterns.email = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;

          ??? //匹配日期格式2008-01-31,但不匹配2008-13-00
          ??? patterns.date = /^\d{4}-(0?[1-9]|1[0-2])-(0?[1-9]|[1-2]\d|3[0-1])$/;
          ???
          ??? /**//*匹配時間格式00:15:39,但不匹配24:60:00,下面使用RegExp對象的構造方法
          ??? 來創建RegExp對象實例,注意正則表達式模式文本中的“\”要寫成“\\”*/
          ??? patterns.time = new RegExp("^([0-1]\\d|2[0-3]):[0-5]\\d:[0-5]\\d$");
          ???????
          ??? /**//*verify – 校驗一個字符串是否符合某種模式
          ???? *str – 要進行校驗的字符串
          ???? *pat – 與patterns中的某個正則表達式模式對應的屬性名稱
          ???? */
          ??? function verify(str,pat)
          ??? {???????
          ??????? thePat = patterns[pat];
          ??????? if(thePat.test(str))
          ??????? {
          ??????????? return true;
          ??????? }
          ??????? else
          ??????? {
          ??????????? return false;
          ??????? }
          ??? }
          </script>

          posted @ 2006-10-14 00:09 CoderDream 閱讀(447) | 評論 (0)編輯 收藏
          正則表達式(REs)通常被錯誤地認為是只有少數人理解的一種神秘語言。在表面上它們確實看起來雜亂無章,如果你不知道它的語法,那么它的代碼在你眼里只是一堆文字垃圾而已。實際上,正則表達式是非常簡單并且可以被理解。讀完這篇文章后,你將會通曉正則表達式的通用語法。

          支持多種平臺

          正則表達式最早是由數學家Stephen Kleene于1956年提出,他是在對自然語言的遞增研究成果的基礎上提出來的。具有完整語法的正則表達式使用在字符的格式匹配方面上,后來被應用到熔融信息技術領域。自從那時起,正則表達式經過幾個時期的發展,現在的標準已經被ISO(國際標準組織)批準和被Open Group組織認定。

          正則表達式并非一門專用語言,但它可用于在一個文件或字符里查找和替代文本的一種標準。它具有兩種標準:基本的正則表達式(BRE),擴展的正則表達式(ERE)。ERE包括BRE功能和另外其它的概念。

          許多程序中都使用了正則表達式,包括xsh,egrep,sed,vi以及在UNIX平臺下的程序。它們可以被很多語言采納,如HTML 和XML,這些采納通常只是整個標準的一個子集。

          比你想象的還要普通

          隨著正則表達式移植到交叉平臺的程序語言的發展,這的功能也日益完整,使用也逐漸廣泛。網絡上的搜索引擎使用它,e-mail程序也使用它,即使你不是一個UNIX程序員,你也可以使用規則語言來簡化你的程序而縮短你的開發時間。

          正則表達式101

          很多正則表達式的語法看起來很相似,這是因為你以前你沒有研究過它們。通配符是RE的一個結構類型,即重復操作。讓我們先看一看ERE標準的最通用的基本語法類型。為了能夠提供具有特定用途的范例,我將使用幾個不同的程序。

          字符匹配


          正則表達式的關鍵之處在于確定你要搜索匹配的東西,如果沒有這一概念,Res將毫無用處。

          每一個表達式都包含需要查找的指令,如表A所示。

          Table A: Character-matching regular expressions

          操作

          解釋

          例子

          結果

          .

          Match any one character

          grep .ord sample.txt

          Will match “ford”, “lord”, “2ord”, etc. in the file sample.txt.

          [ ]

          Match any one character listed between the brackets

          grep [cng]ord sample.txt

          Will match only “cord”, “nord”, and “gord”

          [^ ]

          Match any one character not listed between the brackets

          grep [^cn]ord sample.txt

          Will match “lord”, “2ord”, etc. but not “cord” or “nord”

          grep [a-zA-Z]ord sample.txt

          Will match “aord”, “bord”, “Aord”, “Bord”, etc.

          grep [^0-9]ord sample.txt

          Will match “Aord”, “aord”, etc. but not “2ord”, etc.


          重復操作符

          重復操作符,或數量詞,都描述了查找一個特定字符的次數。它們常被用于字符匹配語法以查找多行的字符,可參見表B。

          Table B: Regular expression repetition operators

          操作

          解釋

          例子

          結果

          ?

          Match any character one time, if it exists

          egrep “?erd” sample.txt

          Will match “berd”, “herd”, etc. and “erd”

          *

          Match declared element multiple times, if it exists

          egrep “n.*rd” sample.txt

          Will match “nerd”, “nrd”, “neard”, etc.

          +

          Match declared element one or more times

          egrep “[n]+erd” sample.txt

          Will match “nerd”, “nnerd”, etc., but not “erd”

          {n}

          Match declared element exactly n times

          egrep “[a-z]{2}erd” sample.txt

          Will match “cherd”, “blerd”, etc. but not “nerd”, “erd”, “buzzerd”, etc.

          {n,}

          Match declared element at least n times

          egrep “.{2,}erd” sample.txt

          Will match “cherd” and “buzzerd”, but not “nerd”

          {n,N}

          Match declared element at least n times, but not more than N times

          egrep “n[e]{1,2}rd” sample.txt

          Will match “nerd” and “neerd”

          錨是指它所要匹配的格式,如圖C所示。使用它能方便你查找通用字符的合并。例如,我用vi行編輯器命令:s來代表substitute,這一命令的基本語法是:

          s/pattern_to_match/pattern_to_substitute/
          ?

          Table C: Regular expression anchors

          操作

          解釋

          例子

          結果

          ^

          Match at the beginning of a line

          s/^/blah /

          Inserts “blah “ at the beginning of the line

          $

          Match at the end of a line

          s/$/ blah/

          Inserts “ blah” at the end of the line

          \<

          Match at the beginning of a word

          s/\</blah/

          Inserts “blah” at the beginning of the word

          egrep “\<blah” sample.txt

          Matches “blahfield”, etc.

          \>

          Match at the end of a word

          s/\>/blah/

          Inserts “blah” at the end of the word

          egrep “\>blah” sample.txt

          Matches “soupblah”, etc.

          \b

          Match at the beginning or end of a word

          egrep “\bblah” sample.txt

          Matches “blahcake” and “countblah”

          \B

          Match in the middle of a word

          egrep “\Bblah” sample.txt

          Matches “sublahper”, etc.


          間隔

          Res中的另一可便之處是間隔(或插入)符號。實際上,這一符號相當于一個OR語句并代表|符號。下面的語句返回文件sample.txt中的“nerd” 和 “merd”的句柄:

          egrep “(n|m)erd” sample.txt

          間隔功能非常強大,特別是當你尋找文件不同拼寫的時候,但你可以在下面的例子得到相同的結果:

          egrep “[nm]erd” sample.txt

          當你使用間隔功能與Res的高級特性連接在一起時,它的真正用處更能體現出來。

          一些保留字符

          Res的最后一個最重要特性是保留字符(也稱特定字符)。例如,如果你想要查找“ne*rd”和“ni*rd”的字符,格式匹配語句“n[ei]*rd”與“neeeeerd” 和 “nieieierd”相符合,但并不是你要查找的字符。因為‘*’(星號)是個保留字符,你必須用一個反斜線符號來替代它,即:“n[ei]\*rd”。其它的保留字符包括:

          • ^ (carat)
          • . (period)
          • [ (left bracket}
          • $ (dollar sign)
          • ( (left parenthesis)
          • ) (right parenthesis)
          • | (pipe)
          • * (asterisk)
          • + (plus symbol)
          • ? (question mark)
          • { (left curly bracket, or left brace)
          • \ backslash

          一旦你把以上這些字符包括在你的字符搜索中,毫無疑問Res變得非常的難讀。比如說以下的PHP中的eregi搜索引擎代碼就很難讀了。

          eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*$",$sendto)

          你可以看到,程序的意圖很難把握。但如果你拋開保留字符,你常常會錯誤地理解代碼的意思。

          總結

          在本文中,我們揭開了正則表達式的神秘面紗,并列出了ERE標準的通用語法。如果你想閱覽Open Group組織的規則的完整描述,你可以參見: Regular Expressions ,歡迎你在其中的討論區發表你的問題或觀點。

          posted @ 2006-10-14 00:03 CoderDream 閱讀(276) | 評論 (0)編輯 收藏

            如果我們問那些UNIX系統的愛好者他們最喜歡什么,答案除了穩定的系統和可以遠程啟動之外,十有八九的人會提到正則表達式;如果我們再問他們最頭痛的是什么,可能除了復雜的進程控制和安裝過程之外,還會是正則表達式。那么正則表達式到底是什么?如何才能真正的掌握正則表達式并正確的加以靈活運用?本文將就此展開介紹,希望能夠對那些渴望了解和掌握正則表達式的讀者有所助益。

          入門簡介

            簡單的說,正則表達式是一種可以用于模式匹配和替換的強有力的工具。我們可以在幾乎所有的基于UNIX系統的工具中找到正則表達式的身影,例如,vi編輯器,Perl或PHP腳本語言,以及awk或sed shell程序等。此外,象JavaScript這種客戶端的腳本語言也提供了對正則表達式的支持。由此可見,正則表達式已經超出了某種語言或某個系統的局限,成為人們廣為接受的概念和功能。

            正則表達式可以讓用戶通過使用一系列的特殊字符構建匹配模式,然后把匹配模式與數據文件、程序輸入以及WEB頁面的表單輸入等目標對象進行比較,根據比較對象中是否包含匹配模式,執行相應的程序。

            舉例來說,正則表達式的一個最為普遍的應用就是用于驗證用戶在線輸入的郵件地址的格式是否正確。如果通過正則表達式驗證用戶郵件地址的格式正確,用戶所填寫的表單信息將會被正常處理;反之,如果用戶輸入的郵件地址與正則表達的模式不匹配,將會彈出提示信息,要求用戶重新輸入正確的郵件地址。由此可見正則表達式在WEB應用的邏輯判斷中具有舉足輕重的作用。

          基本語法

            在對正則表達式的功能和作用有了初步的了解之后,我們就來具體看一下正則表達式的語法格式。

            正則表達式的形式一般如下:

            /love/

            其中位于“/”定界符之間的部分就是將要在目標對象中進行匹配的模式。用戶只要把希望查找匹配對象的模式內容放入“/”定界符之間即可。為了能夠使用戶更加靈活的定制模式內容,正則表達式提供了專門的“元字符”。所謂元字符就是指那些在正則表達式中具有特殊意義的專用字符,可以用來規定其前導字符(即位于元字符前面的字符)在目標對象中的出現模式。

            較為常用的元字符包括: “+”, “*”,以及 “?”。其中,“+”元字符規定其前導字符必須在目標對象中連續出現一次或多次,“*”元字符規定其前導字符必須在目標對象中出現零次或連續多次,而“?”元字符規定其前導對象必須在目標對象中連續出現零次或一次。

            下面,就讓我們來看一下正則表達式元字符的具體應用。

            /fo+/

            因為上述正則表達式中包含“+”元字符,表示可以與目標對象中的 “fool”, “fo”, 或者 “football”等在字母f后面連續出現一個或多個字母o的字符串相匹配。

            /eg*/

            因為上述正則表達式中包含“*”元字符,表示可以與目標對象中的 “easy”, “ego”, 或者 “egg”等在字母e后面連續出現零個或多個字母g的字符串相匹配。

            /Wil?/

            因為上述正則表達式中包含“?”元字符,表示可以與目標對象中的 “Will”, 或者 “Wilson”,等在字母i后面連續出現零個或一個字母l的字符串相匹配。

            除了元字符之外,用戶還可以精確指定模式在匹配對象中出現的頻率。例如,

            /jim{2,6}/

            上述正則表達式規定字符m可以在匹配對象中連續出現2-6次,因此,上述正則表達式可以同jimmy或jimmmmmy等字符串相匹配。

            在對如何使用正則表達式有了初步了解之后,我們來看一下其它幾個重要的元字符的使用方式。

            s:用于匹配單個空格符,包括tab鍵和換行符;

            S:用于匹配除單個空格符之外的所有字符;

            d:用于匹配從0到9的數字;

            w:用于匹配字母,數字或下劃線字符;

            W:用于匹配所有與w不匹配的字符;

            . :用于匹配除換行符之外的所有字符。

            (說明:我們可以把s和S以及w和W看作互為逆運算)

            下面,我們就通過實例看一下如何在正則表達式中使用上述元字符。

            /s+/

            上述正則表達式可以用于匹配目標對象中的一個或多個空格字符。

            /d000/

            如果我們手中有一份復雜的財務報表,那么我們可以通過上述正則表達式輕而易舉的查找到所有總額達千元的款項。

            除了我們以上所介紹的元字符之外,正則表達式中還具有另外一種較為獨特的專用字符,即定位符。定位符用于規定匹配模式在目標對象中的出現位置。

            較為常用的定位符包括: “^”, “$”, “” 以及 “B”。其中,“^”定位符規定匹配模式必須出現在目標字符串的開頭,“$”定位符規定匹配模式必須出現在目標對象的結尾,定位符規定匹配模式必須出現在目標字符串的開頭或結尾的兩個邊界之一,而“B”定位符則規定匹配對象必須位于目標字符串的開頭和結尾兩個邊界之內,即匹配對象既不能作為目標字符串的開頭,也不能作為目標字符串的結尾。同樣,我們也可以把“^”和“$”以及“”和“B”看作是互為逆運算的兩組定位符。舉例來說:

            /^hell/

            因為上述正則表達式中包含“^”定位符,所以可以與目標對象中以 “hell”, “hello”或 “hellhound”開頭的字符串相匹配。

            /ar$/

            因為上述正則表達式中包含“$”定位符,所以可以與目標對象中以 “car”, “bar”或 “ar” 結尾的字符串相匹配。

            /bom/

            因為上述正則表達式模式以“”定位符開頭,所以可以與目標對象中以 “bomb”, 或 “bom”開頭的字符串相匹配。

            /man/

            因為上述正則表達式模式以“”定位符結尾,所以可以與目標對象中以 “human”, “woman”或 “man”結尾的字符串相匹配。

            為了能夠方便用戶更加靈活的設定匹配模式,正則表達式允許使用者在匹配模式中指定某一個范圍而不局限于具體的字符。例如:

            /[A-Z]/

            上述正則表達式將會與從A到Z范圍內任何一個大寫字母相匹配。

            /[a-z]/

            上述正則表達式將會與從a到z范圍內任何一個小寫字母相匹配。

            /[0-9]/

            上述正則表達式將會與從0到9范圍內任何一個數字相匹配。

            /([a-z][A-Z][0-9])+/

            上述正則表達式將會與任何由字母和數字組成的字符串,如 “aB0” 等相匹配。這里需要提醒用戶注意的一點就是可以在正則表達式中使用 “()” 把字符串組合在一起。“()”符號包含的內容必須同時出現在目標對象中。因此,上述正則表達式將無法與諸如 “abc”等的字符串匹配,因為“abc”中的最后一個字符為字母而非數字。

            如果我們希望在正則表達式中實現類似編程邏輯中的“或”運算,在多個不同的模式中任選一個進行匹配的話,可以使用管道符 “|”。例如:

            /to|too|2/

            上述正則表達式將會與目標對象中的 “to”, “too”, 或 “2” 相匹配。

            正則表達式中還有一個較為常用的運算符,即否定符 “[^]”。與我們前文所介紹的定位符 “^” 不同,否定符 “[^]”規定目標對象中不能存在模式中所規定的字符串。例如:

            /[^A-C]/

            上述字符串將會與目標對象中除A,B,和C之外的任何字符相匹配。一般來說,當“^”出現在 “[]”內時就被視做否定運算符;而當“^”位于“[]”之外,或沒有“[]”時,則應當被視做定位符。

            最后,當用戶需要在正則表達式的模式中加入元字符,并查找其匹配對象時,可以使用轉義符“”。例如:

            /Th*/

            上述正則表達式將會與目標對象中的“Th*”而非“The”等相匹配。

            使用實例

            在對正則表達式有了較為全面的了解之后,我們就來看一下如何在Perl,PHP,以及JavaScript中使用正則表達式。

            通常,Perl中正則表達式的使用格式如下:

            operator / regular-expression / string-to-replace / modifiers

            運算符一項可以是m或s,分別代表匹配運算和替換運算。

            其中,正則表達式一項是將要進行匹配或替換操作的模式,可以由任意字符,元字符,或定位符等組成。替換字符串一項是使用s運算符時,對查找到的模式匹配對象進行替換的字符串。最后的參數項用來控制不同的匹配或替換方式。例如:

            s/geed/good/

            將會在目標對象中查找第一個出現的geed字串,并將其替換為good。如果我們希望在目標對象的全局范圍內執行多次查找—替換操作的話,可以使用參數 “g”,即s/love/lust/g。

            此外,如果我們不需要限制匹配的大小寫形式的話,可以使用參數 “i ”。例如,

            m/JewEL/i

            上述正則表達式將會與目標對象中的jewel,Jewel,或JEWEL相匹配。

            在Perl中,使用專門的運算符“=~”指定正則表達式的匹配對象。例如:

            $flag =~ s/abc/ABC/

            上述正則表達式將會把變量$flag中的字串abc替換為ABC。

            下面,我們就在Perl程序中加入正則表達式,驗證用戶郵件地址格式的有效性。代碼如下:

            #!/usr/bin/perl
            # get input
            print “What's your email address? ”;
            $email = <>
            chomp($email);
            # match and display result
            if($email =~ /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/)
            {
            print(“Your email address is correct! ”);
            }
            else
             {
              print(“Please try again! ”);
             }

            如果用戶更偏愛PHP的話,可以使用ereg()函數進行模式匹配操作。ereg()函數的使用格式如下:
             ereg(pattern, string)

            其中,pattern代表正則表達式的模式,而string則是執行查找替換操作的目標對象。同樣是驗證郵件地址,使用PHP編寫的程序代碼如下:

            <?php
             if (ereg(“^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+”,$email))
              { echo “Your email address is correct!”;}
             else
              { echo “Please try again!”;}
             ?>
            最后,我們在來看一下JavaScript。JavaScript 1.2中帶有一個功能強大的RegExp()對象,可以用來進行正則表達式的匹配操作。其中的test()方法可以檢驗目標對象中是否包含匹配模式,并相應的返回true或false。

            我們可以使用JavaScript編寫以下腳本,驗證用戶輸入的郵件地址的有效性。

            <html>
             <head>
              < language="Javascript1.2">
               <!-- start hiding
               function verifyAddress(obj)
               {
                var email = obj.email.value;
                var pattern = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/;
                flag = pattern.test(email);
                if(flag)
                {
                 alert(“Your email address is correct!”);
                 return true;
                }
                else
                 {
                  alert(“Please try again!”);
                  return false;
                  }
                }
               // stop hiding -->
              </script>
             </head>
             <body>
             <form onSubmit="return verifyAddress(this);">
             <input name="email" type="text">
             <input type="submit" value="提交">
             </form>
            </body>
           </html>

          posted @ 2006-10-13 23:57 CoderDream 閱讀(385) | 評論 (0)編輯 收藏

          正則表達式之道

          原著:Steve Mansour
          sman@scruznet.com
          Revised: June 5, 1999
          (copied by jm /at/ jmason.org from http://www.scruz.net/%7esman/regexp.htm, after the original disappeared! )

          翻譯:Neo Lee
          neo.lee@gmail.com
          2004年10月16日


          英文版原文

          譯者按:原文因為年代久遠,文中很多鏈接早已過期(主要是關于vi、sed等工具的介紹和手冊),本譯文中已將此類鏈接刪除,如需檢查這些鏈接可以查看上面鏈接的原文。除此之外基本照原文直譯,括號中有“譯者按”的部分是譯者補充的說明。如有內容方面的問題請直接和Steve Mansor聯系,當然,如果你只寫中文,也可以和我聯系。


          目 錄

          什么是正則表達式
          范例
          ?? 簡單
          ?? 中級(神奇的咒語)
          ?? 困難(不可思議的象形文字)
          不同工具中的正則表達式


          什么是正則表達式

          一個正則表達式,就是用某種模式去匹配一類字符串的一個公式。很多人因為它們看上去比較古怪而且復雜所以不敢去使用——很不幸,這篇文章也不能夠改變這一點,不過,經過一點點練習之后我就開始覺得這些復雜的表達式其實寫起來還是相當簡單的,而且,一旦你弄懂它們,你就能把數小時辛苦而且易錯的文本處理工作壓縮在幾分鐘(甚至幾秒鐘)內完成。正則表達式被各種文本編輯軟件、類庫(例如Rogue Wave的tools.h++)、腳本工具(像awk/grep/sed)廣泛的支持,而且像Microsoft的Visual C++這種交互式IDE也開始支持它了。

          我們將在如下的章節中利用一些例子來解釋正則表達式的用法,絕大部分的例子是基于vi中的文本替換命令和grep文件搜索命令來書寫的,不過它們都是比較典型的例子,其中的概念可以在sed、awk、perl和其他支持正則表達式的編程語言中使用。你可以看看不同工具中的正則表達式這一節,其中有一些在別的工具中使用正則表達式的例子。還有一個關于vi中文本替換命令(s)的簡單說明附在文后供參考。

          正則表達式基礎

          正則表達式由一些普通字符和一些元字符(metacharacters)組成。普通字符包括大小寫的字母和數字,而元字符則具有特殊的含義,我們下面會給予解釋。

          在最簡單的情況下,一個正則表達式看上去就是一個普通的查找串。例如,正則表達式"testing"中沒有包含任何元字符,,它可以匹配"testing"和"123testing"等字符串,但是不能匹配"Testing"。

          要想真正的用好正則表達式,正確的理解元字符是最重要的事情。下表列出了所有的元字符和對它們的一個簡短的描述。

          元字符?描述


          .
          匹配任何單個字符。例如正則表達式r.t匹配這些字符串:ratrutr t,但是不匹配root。?
          $
          匹配行結束符。例如正則表達式weasel$ 能夠匹配字符串"He's a weasel"的末尾,但是不能匹配字符串"They are a bunch of weasels."。?
          ^
          匹配一行的開始。例如正則表達式^When in能夠匹配字符串"When in the course of human events"的開始,但是不能匹配"What and When in the"。
          *
          匹配0或多個正好在它之前的那個字符。例如正則表達式.*意味著能夠匹配任意數量的任何字符。
          \
          這是引用府,用來將這里列出的這些元字符當作普通的字符來進行匹配。例如正則表達式\$被用來匹配美元符號,而不是行尾,類似的,正則表達式\.用來匹配點字符,而不是任何字符的通配符。
          [ ]?
          [c1-c2]
          [^c1-c2]
          匹配括號中的任何一個字符。例如正則表達式r[aou]t匹配ratrotrut,但是不匹配ret。可以在括號中使用連字符-來指定字符的區間,例如正則表達式[0-9]可以匹配任何數字字符;還可以制定多個區間,例如正則表達式[A-Za-z]可以匹配任何大小寫字母。另一個重要的用法是“排除”,要想匹配除了指定區間之外的字符——也就是所謂的補集——在左邊的括號和第一個字符之間使用^字符,例如正則表達式[^269A-Z] 將匹配除了2、6、9和所有大寫字母之外的任何字符。
          \< \>
          匹配詞(word)的開始(\<)和結束(\>)。例如正則表達式\<the能夠匹配字符串"for the wise"中的"the",但是不能匹配字符串"otherwise"中的"the"。注意:這個元字符不是所有的軟件都支持的。
          \( \)
          將 \( 和 \) 之間的表達式定義為“組”(group),并且將匹配這個表達式的字符保存到一個臨時區域(一個正則表達式中最多可以保存9個),它們可以用 \1\9 的符號來引用。
          |
          將兩個匹配條件進行邏輯“或”(Or)運算。例如正則表達式(him|her) 匹配"it belongs to him"和"it belongs to her",但是不能匹配"it belongs to them."。注意:這個元字符不是所有的軟件都支持的。
          +
          匹配1或多個正好在它之前的那個字符。例如正則表達式9+匹配9、99、999等。注意:這個元字符不是所有的軟件都支持的。
          ?
          匹配0或1個正好在它之前的那個字符。注意:這個元字符不是所有的軟件都支持的。
          \{i\}
          \{i,j\}
          匹配指定數目的字符,這些字符是在它之前的表達式定義的。例如正則表達式A[0-9]\{3\} 能夠匹配字符"A"后面跟著正好3個數字字符的串,例如A123、A348等,但是不匹配A1234。而正則表達式[0-9]\{4,6\} 匹配連續的任意4個、5個或者6個數字字符。注意:這個元字符不是所有的軟件都支持的。


          最簡單的元字符是點,它能夠匹配任何單個字符(注意包括新行符)。假定有個文件test.txt包含以下幾行內容:

            he is a rat
            he is in a rut
            the food is Rotten
            I like root beer
          我們可以使用grep命令來測試我們的正則表達式,grep命令使用正則表達式去嘗試匹配指定文件的每一行,并將至少有一處匹配表達式的所有行顯示出來。命令
            grep r.t test.txt
          在test.txt文件中的每一行中搜索正則表達式r.t,并打印輸出匹配的行。正則表達式r.t匹配一個r接著任何一個字符再接著一個t。所以它將匹配文件中的ratrut,而不能匹配Rotten中的Rot,因為正則表達式是大小寫敏感的。要想同時匹配大寫和小寫字母,應該使用字符區間元字符(方括號)。正則表達式[Rr]能夠同時匹配Rr。所以,要想匹配一個大寫或者小寫的r接著任何一個字符再接著一個t就要使用這個表達式:[Rr].t

          要想匹配行首的字符要使用抑揚字符(^)——又是也被叫做插入符。例如,想找到text.txt中行首"he"打頭的行,你可能會先用簡單表達式he,但是這會匹配第三行的the,所以要使用正則表達式^he,它只匹配在行首出現的h

          有時候指定“除了×××都匹配”會比較容易達到目的,當抑揚字符(^)出現在方括號中是,它表示“排除”,例如要匹配he ,但是排除前面是t or s的情性(也就是theshe),可以使用:[^st]he

          可以使用方括號來指定多個字符區間。例如正則表達式[A-Za-z]匹配任何字母,包括大寫和小寫的;正則表達式[A-Za-z][A-Za-z]* 匹配一個字母后面接著0或者多個字母(大寫或者小寫)。當然我們也可以用元字符+做到同樣的事情,也就是:[A-Za-z]+ ,和[A-Za-z][A-Za-z]*完全等價。但是要注意元字符+ 并不是所有支持正則表達式的程序都支持的。關于這一點可以參考后面的正則表達式語法支持情況

          要指定特定數量的匹配,要使用大括號(注意必須使用反斜杠來轉義)。想匹配所有1001000的實例而排除1010000,可以使用:10\{2,3\},這個正則表達式匹配數字1后面跟著2或者3個0的模式。在這個元字符的使用中一個有用的變化是忽略第二個數字,例如正則表達式0\{3,\} 將匹配至少3個連續的0。

          簡單的例子

          這里有一些有代表性的、比較簡單的例子。

          vi 命令作用


          :%s/ */ /g把一個或者多個空格替換為一個空格。
          :%s/ *$//去掉行尾的所有空格。
          :%s/^/ /在每一行頭上加入一個空格。
          :%s/^[0-9][0-9]* //去掉行首的所有數字字符。
          :%s/b[aeio]g/bug/g將所有的bagbegbigbog改為bug。?
          :%s/t\([aou]\)g/h\1t/g將所有tagtogtug分別改為hathothug(注意用group的用法和使用\1引用前面被匹配的字符)。

          中級的例子(神奇的咒語)

          例1

          將所有方法foo(a,b,c)的實例改為foo(b,a,c)。這里a、b和c可以是任何提供給方法foo()的參數。也就是說我們要實現這樣的轉換:

          之前?之后
          foo(10,7,2)foo(7,10,2)
          foo(x+13,y-2,10)foo(y-2,x+13,10)
          foo( bar(8), x+y+z, 5)foo( x+y+z, bar(8), 5)

          下面這條替換命令能夠實現這一魔法:

            :%s/foo(\([^,]*\),\([^,]*\),\([^)]*\))/foo(\2,\1,\3)/g

          現在讓我們把它打散來加以分析。寫出這個表達式的基本思路是找出foo()和它的括號中的三個參數的位置。第一個參數是用這個表達式來識別的::\([^,]*\),我們可以從里向外來分析它:?

          [^,]?除了逗號之外的任何字符
          [^,]*0或者多個非逗號字符
          \([^,]*\)將這些非逗號字符標記為\1,這樣可以在之后的替換模式表達式中引用它
          \([^,]*\),我們必須找到0或者多個非逗號字符后面跟著一個逗號,并且非逗號字符那部分要標記出來以備后用。

          現在正是指出一個使用正則表達式常見錯誤的最佳時機。為什么我們要使用[^,]*這樣的一個表達式,而不是更加簡單直接的寫法,例如:.*,來匹配第一個參數呢?設想我們使用模式.*來匹配字符串"10,7,2",它應該匹配"10,"還是"10,7,"?為了解決這個兩義性(ambiguity),正則表達式規定一律按照最長的串來,在上面的例子中就是"10,7,",顯然這樣就找出了兩個參數而不是我們期望的一個。所以,我們要使用[^,]*來強制取出第一個逗號之前的部分。

          這個表達式我們已經分析到了:foo(\([^,]*\),這一段可以簡單的翻譯為“當你找到foo(就把其后直到第一個逗號之前的部分標記為\1”。然后我們使用同樣的辦法標記第二個參數為\2。對第三個參數的標記方法也是一樣,只是我們要搜索所有的字符直到右括號。我們并沒有必要去搜索第三個參數,因為我們不需要調整它的位置,但是這樣的模式能夠保證我們只去替換那些有三個參數的foo()方法調用,在foo()是一個重載(overoading)方法時這種明確的模式往往是比較保險的。然后,在替換部分,我們找到foo()的對應實例,然后利用標記好的部分進行替換,是的第一和第二個參數交換位置。

          例2

          假設有一個CSV(comma separated value)文件,里面有一些我們需要的信息,但是格式卻有問題,目前數據的列順序是:姓名,公司名,州名縮寫,郵政編碼,現在我們希望講這些數據重新組織,以便在我們的某個軟件中使用,需要的格式為:姓名,州名縮寫-郵政編碼,公司名。也就是說,我們要調整列順序,還要合并兩個列來構成一個新列。另外,我們的軟件不能接受逗號前后面有任何空格(包括空格和制表符)所以我們還必須要去掉逗號前后的所有空格。

          這里有幾行我們現在的數據:

            Bill Jones,???? HI-TEK Corporation ,? CA, 95011
            Sharon Lee Smith,? Design Works Incorporated,? CA, 95012
            B. Amos?? ,? Hill Street Cafe,? CA, 95013
            Alexander Weatherworth,? The Crafts Store,? CA, 95014
            ...
          我們希望把它變成這個樣子:
            Bill Jones,CA 95011,HI-TEK Corporation
            Sharon Lee Smith,CA 95012,Design Works Incorporated
            B. Amos,CA 95013,Hill Street Cafe
            Alexander Weatherworth,CA 95014,The Crafts Store
            ...
          我們將用兩個正則表達式來解決這個問題。第一個移動列和合并列,第二個用來去掉空格。

          下面就是第一個替換命令:

            :%s/\([^,]*\),\([^,]*\),\([^,]*\),\(.*\)/\1,\3 \4,\2/
          這里的方法跟例1基本一樣,第一個列(姓名)用這個表達式來匹配:\([^,]*\),即第一個逗號之前的所有字符,而姓名內容被用\1標記下來。公司名和州名縮寫字段用同樣的方法標記為\2\3,而最后一個字段用\(.*\)來匹配("匹配所有字符直到行末")。替換部分則引用上面標記的那些內容來進行構造。

          下面這個替換命令則用來去除空格:

            :%s/[ \t]*,[ \t]*/,/g
          我們還是分解來看:[ \t]匹配空格/制表符,[ \t]* 匹配0或多個空格/制表符,[ \t]*,匹配0或多個空格/制表符后面再加一個逗號,最后,[ \t]*,[ \t]*匹配0或多個空格/制表符接著一個逗號再接著0或多個空格/制表符。在替換部分,我們簡單的我們找到的所有東西替換成一個逗號。這里我們使用了結尾的可選的g參數,這表示在每行中對所有匹配的串執行替換(而不是缺省的只替換第一個匹配串)。

          例3

          假設有一個多字符的片斷重復出現,例如:
          Billy tried really hard
          Sally tried really really hard
          Timmy tried really really really hard
          Johnny tried really really really really hard
          而你想把"really"、"really really",以及任意數量連續出現的"really"字符串換成一個簡單的"very"(simple is good!),那么以下命令:
          :%s/\(really \)\(really \)*/very /
          就會把上述的文本變成:
          Billy tried very hard
          Sally tried very hard
          Timmy tried very hard
          Johnny tried very hard
          表達式\(really \)*匹配0或多個連續的"really "(注意結尾有個空格),而\(really \)\(really \)* 匹配1個或多個連續的"really "實例。

          困難的例子(不可思議的象形文字)

          Coming soon.


          不同工具中的正則表達式

          OK,你已經準備使用RE(regular expressions,正則表達式),但是你并準備使用vi。所以,在這里我們給出一些在其他工具中使用RE的例子。另外,我還會總結一下你在不同程序之間使用RE可能發現的區別。

          當然,你也可以在Visual C++編輯器中使用RE。選擇Edit->Replace,然后選擇"Regular expression"選擇框,Find What輸入框對應上面介紹的vi命令:%s/pat1/pat2/g中的pat1部分,而Replace輸入框對應pat2部分。但是,為了得到vi的執行范圍和g選項,你要使用Replace All或者適當的手工Find Next and Replace(譯者按:知道為啥有人罵微軟弱智了吧,雖然VC中可以選中一個范圍的文本,然后在其中執行替換,但是總之不夠vi那么靈活和典雅)。

          sed

          Sed是Stream EDitor的縮寫,是Unix下常用的基于文件和管道的編輯工具,可以在手冊中得到關于sed的詳細信息。

          這里是一些有趣的sed腳本,假定我們正在處理一個叫做price.txt的文件。注意這些編輯并不會改變源文件,sed只是處理源文件的每一行并把結果顯示在標準輸出中(當然很容易使用重定向來定制):

          sed腳本?描述


          sed 's/^$/d' price.txt刪除所有空行
          sed 's/^[ \t]*$/d' price.txt刪除所有只包含空格或者制表符的行
          sed 's/"http://g' price.txt刪除所有引號

          awk

          awk是一種編程語言,可以用來對文本數據進行復雜的分析和處理。可以在手冊中得到關于awk的詳細信息。這個古怪的名字是它作者們的姓的縮寫(Aho,Weinberger和Kernighan)。

          在Aho,Weinberger和Kernighan的書The AWK Programming Language中有很多很好的awk的例子,請不要讓下面這些微不足道的腳本例子限制你對awk強大能力的理解。我們同樣假定我們針對price.txt文件進行處理,跟sed一樣,awk也只是把結果顯示在終端上。?

          awk腳本?描述


          awk '$0 !~ /^$/' price.txt刪除所有空行
          awk 'NF > 0' price.txtawk中一個更好的刪除所有行的辦法
          awk '$2 ~ /^[JT]/ {print $3}' price.txt打印所有第二個字段是'J'或者'T'打頭的行中的第三個字段
          awk '$2 !~ /[Mm]isc/ {print $3 + $4}' price.txt針對所有第二個字段不包含'Misc'或者'misc'的行,打印第3和第4列的和(假定為數字)
          awk '$3 !~ /^[0-9]+\.[0-9]*$/ {print $0}' price.txt打印所有第三個字段不是數字的行,這里數字是指d.d或者d這樣的形式,其中d是0到9的任何數字
          awk '$2 ~ /John|Fred/ {print $0}' price.txt如果第二個字段包含'John'或者'Fred'則打印整行

          grep

          grep是一個用來在一個或者多個文件或者輸入流中使用RE進行查找的程序。它的name編程語言可以用來針對文件和管道進行處理。可以在手冊中得到關于grep的完整信息。這個同樣古怪的名字來源于vi的一個命令,g/re/p,意思是global regular expression print。

          下面的例子中我們假定在文件phone.txt中包含以下的文本,——其格式是姓加一個逗號,然后是名,然后是一個制表符,然后是電話號碼:

            Francis, John?????????? 5-3871
            Wong, Fred????????????? 4-4123
            Jones, Thomas?????????? 1-4122
            Salazar, Richard??????? 5-2522

          grep命令?描述


          grep '\t5-...1' phone.txt把所有電話號碼以5開頭以1結束的行打印出來,注意制表符是用\t表示的
          grep '^S[^ ]* R' phone.txt打印所有姓以S打頭和名以R打頭的行
          grep '^[JW]' phone.txt打印所有姓開頭是J或者W的行
          grep ', ....\t' phone.txt打印所有姓是4個字符的行,注意制表符是用\t表示的
          grep -v '^[JW]' phone.txt打印所有不以J或者W開頭的行
          grep '^[M-Z]' phone.txt打印所有姓的開頭是M到Z之間任一字符的行
          grep '^[M-Z].*[12]' phone.txt打印所有姓的開頭是M到Z之間任一字符,并且點號號碼結尾是1或者2的行

          egrep

          egrep是grep的一個擴展版本,它在它的正則表達式中支持更多的元字符。下面的例子中我們假定在文件phone.txt中包含以下的文本,——其格式是姓加一個逗號,然后是名,然后是一個制表符,然后是電話號碼:
            Francis, John?????????? 5-3871
            Wong, Fred????????????? 4-4123
            Jones, Thomas?????????? 1-4122
            Salazar, Richard??????? 5-2522

          egrep command?Description


          egrep '(John|Fred)' phone.txt打印所有包含名字John或者Fred的行
          egrep 'John|22$|^W' phone.txt打印所有包含John 或者以22結束或者以W的行
          egrep 'net(work)?s' report.txt從report.txt中找到所有包含networks或者nets的行


          正則表達式語法支持情況

          命令或環境.[ ]^$\( \)\{ \}?+|( )
          vi?X??X??X??X??X??????
          Visual C++?X??X??X??X??X??????
          awk?X??X??X??X????X??X??X??X?
          sed?X??X??X??X??X??X?????
          Tcl?X??X??X??X??X???X??X??X??X?
          ex?X??X??X??X??X??X?????
          grep?X??X??X??X??X??X?????
          egrep?X??X?X??X??X???X??X??X??X?
          fgrep?X??X??X??X??X??????
          perl?X?X?X?X?X??X?X?X?X

          ?


          vi替換命令簡介

          Vi的替換命令:
            :ranges/pat1/pat2/g
          其中
            : 這是Vi的命令執行界面。
            range 是命令執行范圍的指定,可以使用百分號(%)表示所有行,使用點(.)表示當前行,使用美元符號($)表示最后一行。你還可以使用行號,例如10,20表示第10到20行,.,$表示當前行到最后一行,.+2,$-5表示當前行后兩行直到全文的倒數第五行,等等。

            s 表示其后是一個替換命令。

            pat1 這是要查找的一個正則表達式,這篇文章中有一大堆例子。

            pat2 這是希望把匹配串變成的模式的正則表達式,這篇文章中有一大堆例子。

            g 可選標志,帶這個標志表示替換將針對行中每個匹配的串進行,否則則只替換行中第一個匹配串。

          網上有很多vi的在線手冊,你可以訪問他們以獲得更加完整的信息。


          [回到主頁]

          posted @ 2006-10-13 23:53 CoderDream 閱讀(317) | 評論 (0)編輯 收藏

          ?????? 正則表達式(regular expression)對象包含一個正則表達式模式(pattern)。它具有用正則表達式模式去匹配或代替一個串(string)中特定字符(或字符集合)的屬性(properties)和方法(methods)。 要為一個單獨的正則表達式添加屬性,可以使用正則表達式構造函數(constructor function),無論何時被調用的預設置的正則表達式擁有靜態的屬性(the predefined RegExp object has static properties that are set whenever any regular expression is used, 我不知道我翻得對不對,將原文列出,請自行翻譯)。

          • 創建:
            一個文本格式或正則表達式構造函數
            文本格式: /pattern/flags
            正則表達式構造函數: new RegExp("pattern"[,"flags"]);
          • 參數說明:
            pattern -- 一個正則表達式文本
            flags -- 如果存在,將是以下值:
            g: 全局匹配
            i: 忽略大小寫
            gi: 以上組合

          [注意] 文本格式的參數不用引號,而在用構造函數時的參數需要引號。如:/ab+c/i new RegExp("ab+c","i")是實現一樣的功能。在構造函數中,一些特殊字符需要進行轉意(在特殊字符前加"\")。如:re = new RegExp("\\w+")

          正則表達式中的特殊字符

          字符 含意
          \

          做為轉意,即通常在"\"后面的字符不按原來意義解釋,如/b/匹配字符"b",當b前面加了反斜桿后/\b/,轉意為匹配一個單詞的邊界。
          -或-
          對正則表達式功能字符的還原,如"*"匹配它前面元字符0次或多次,/a*/將匹配a,aa,aaa,加了"\"后,/a\*/將只匹配"a*"。

          ^ 匹配一個輸入或一行的開頭,/^a/匹配"an A",而不匹配"An a"
          $ 匹配一個輸入或一行的結尾,/a$/匹配"An a",而不匹配"an A"
          * 匹配前面元字符0次或多次,/ba*/將匹配b,ba,baa,baaa
          + 匹配前面元字符1次或多次,/ba*/將匹配ba,baa,baaa
          ? 匹配前面元字符0次或1次,/ba*/將匹配b,ba
          (x) 匹配x保存x在名為$1...$9的變量中
          x|y 匹配x或y
          {n} 精確匹配n次
          {n,} 匹配n次以上
          {n,m} 匹配n-m次
          [xyz] 字符集(character set),匹配這個集合中的任一一個字符(或元字符)
          [^xyz] 不匹配這個集合中的任何一個字符
          [\b] 匹配一個退格符
          \b 匹配一個單詞的邊界
          \B 匹配一個單詞的非邊界
          \cX 這兒,X是一個控制符,/\cM/匹配Ctrl-M
          \d 匹配一個字數字符,/\d/ = /[0-9]/
          \D 匹配一個非字數字符,/\D/ = /[^0-9]/
          \n 匹配一個換行符
          \r 匹配一個回車符
          \s 匹配一個空白字符,包括\n,\r,\f,\t,\v等
          \S 匹配一個非空白字符,等于/[^\n\f\r\t\v]/
          \t 匹配一個制表符
          \v 匹配一個重直制表符
          \w 匹配一個可以組成單詞的字符(alphanumeric,這是我的意譯,含數字),包括下劃線,如[\w]匹配"$5.98"中的5,等于[a-zA-Z0-9]
          \W 匹配一個不可以組成單詞的字符,如[\W]匹配"$5.98"中的$,等于[^a-zA-Z0-9]。

          說了這么多了,我們來看一些正則表達式的實際應用的例子:

          E-mail地址驗證:
          ?function test_email(strEmail) {
          ??var myReg = /^[_a-z0-9]+@([_a-z0-9]+\.)+[a-z0-9]{2,3}$/;
          ??if(myReg.test(strEmail)) return true;
          ??return false;
          ?}
          HTML代碼的屏蔽
          ?function mask_HTMLCode(strInput) {
          ?? var myReg = /<(\w+)>/;
          ?? return strInput.replace(myReg, "&lt;$1&gt;");
          ?}

          正則表達式對象的屬性及方法
            預定義的正則表達式擁有有以下靜態屬性:input, multiline, lastMatch, lastParen, leftContext, rightContext和$1到$9。其中input和multiline可以預設置。其他屬性的值在執行過exec或test方法后被根據不同條件賦以不同的值。許多屬性同時擁有長和短(perl風格)的兩個名字,并且,這兩個名字指向同一個值。(JavaScript模擬perl的正則表達式)
          正則表達式對象的屬性
          屬性含義
          $1...$9如果它(們)存在,是匹配到的子串
          $_參見input
          $*參見multiline
          $&參見lastMatch
          $+參見lastParen
          $`參見leftContext
          $’         參見rightContext
          constructor   創建一個對象的一個特殊的函數原型
          global      是否在整個串中匹配(bool型)
          ignoreCase    匹配時是否忽略大小寫(bool型)
          input       被匹配的串
          lastIndex    最后一次匹配的索引
          lastParen    最后一個括號括起來的子串
          leftContext   最近一次匹配以左的子串
          multiline    是否進行多行匹配(bool型)
          prototype    允許附加屬性給對象
          rightContext   最近一次匹配以右的子串
          source      正則表達式模式
          lastIndex    最后一次匹配的索引

          正則表達式對象的方法

          方法含義
          compile     正則表達式比較
          exec       執行查找
          test       進行匹配
          toSource     返回特定對象的定義(literal representing),其值可用來創建一個新的對象。重載Object.toSource方法得到的。
          toString     返回特定對象的串。重載Object.toString方法得到的。
          valueOf     返回特定對象的原始值。重載Object.valueOf方法得到

          例子
          <script language = "JavaScript">
          var myReg = /(\w+)\s(\w+)/;
          var str? = "John Smith";
          var newstr = str.replace(myReg, "$2, $1");
          document.write(newstr);
          </script>
          將輸出"Smith, John"
          posted @ 2006-10-13 23:49 CoderDream 閱讀(179) | 評論 (0)編輯 收藏
          1、如何才能掌握java
          2、Eclipse+MyEclipse+WebLogic8.1配置
          3、用Eclipse+MyEclipse+WebLogic8.1開發第一個Web程序
          4、Weblogic和MyEclipse的配置
          5、Java初學者都必須理解的問題
          posted @ 2006-10-12 20:29 CoderDream 閱讀(190) | 評論 (0)編輯 收藏
          僅列出標題
          共24頁: First 上一頁 16 17 18 19 20 21 22 23 24 下一頁 

          <2025年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          常用鏈接

          留言簿(9)

          我參與的團隊

          隨筆分類(245)

          隨筆檔案(239)

          文章分類(3)

          文章檔案(3)

          收藏夾(576)

          友情鏈接

          搜索

          •  

          積分與排名

          • 積分 - 458389
          • 排名 - 114

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 兰溪市| 永德县| 六枝特区| 屏东县| 永昌县| 黑河市| 浦北县| 揭东县| 阳东县| 京山县| 开化县| 台安县| 曲松县| 民县| 凤城市| 盈江县| 禹州市| 睢宁县| 定襄县| 衡阳县| 永川市| 蛟河市| 金沙县| 武川县| 连州市| 八宿县| 霍林郭勒市| 汪清县| 桑植县| 永福县| 廊坊市| 冀州市| 遂昌县| 新安县| 郓城县| 姜堰市| 泰州市| 精河县| 当雄县| 垦利县| 缙云县|