天天看點

10分鐘學會正則

今天發了一篇關于apache rewrite的日志,因為配置都是用正規表達式寫的,就想翻翻以前的qq空間,把關于正規表達式的内容貼出來。

因為是以前從網上摘的,也忘了是哪摘的了(以前沒有寫來源的習慣),不過在谷歌上把标題打進去會發現很多相同的文章。但是本帖結合了一些東西,是以會比原文内容豐富一些。

首先來看看百度百科的解釋:一個正規表達式,就是用某種模式去比對一類字元串的一個公式。 [百度百科釋義]

想必很多人都對正規表達式都頭疼.今天,我以我的認識,加上網上一些文章,希望用常人都可以了解的表達方式.來和大家分享學習經驗.

開篇,還是得說說 ^ 和 $ 他們是分别用來比對字元串的開始和結束,以下分别舉例說明

”^the”: 開頭一定要有”the”字元串;

”of despair$”: 結尾一定要有”of despair” 的字元串;

那麼,

”^abc$”: 就是要求以abc開頭和以abc結尾的字元串,實際上是隻有abc比對

”notice”: 比對包含notice的字元串

你可以看見如果你沒有用我們提到的兩個字元(最後一個例子),就是說 模式(正規表達式) 可以出現在被檢驗字元串的任何地方,你沒有把他鎖定到兩邊

  接着,說說 ‘*’, ‘+’,和 ‘?’,

他們用來表示一個字元可以出現的次數或者順序. 他們分别表示:

”zero or more”相當于{0,},

”one or more”相當于{1,},

”zero or one.”相當于{0,1}, 這裡是一些例子:

”ab*”: 和ab{0,}同義,比對以a開頭,後面可以接0個或者n個b組成的字元串(“a”, “ab”, “abbb”, 等);

”ab+”: 和ab{1,}同義,同上條一樣,但最少要有一個b存在 (“ab”, “abbb”, 等.);

”ab?”:和ab{0,1}同義,可以沒有或者隻有一個b;

”a?b+$”: 比對以一個或者0個a再加上一個以上的b結尾的字元串.

要點, ‘*’, ‘+’,和 ‘?’隻管它前面那個字元.

  你也可以在大括号裡面限制字元出現的個數,比如

”ab{2}”: 要求a後面一定要跟兩個b(一個也不能少)(“abb”);

”ab{2,}”: 要求a後面一定要有兩個或者兩個以上b(如”abb”, “abbbb”, 等.);

”ab{3,5}”: 要求a後面可以有3-5個b(“abbb”, “abbbb”, or “abbbbb”).

現在我們把一定幾個字元放到小括号裡,比如:

”a(bc)*”: 比對 a 後面跟0個或者一個”bc”;

”a(bc){1,5}”: 一個到5個 “bc.”

還有一個字元 ‘│’, 相當于or 操作:

”hi│hello”: 比對含有”hi” 或者 “hello” 的 字元串;

”(b│cd)ef”: 比對含有 “bef” 或者 “cdef”的字元串;

”(a│b)*c”: 比對含有這樣多個(包括0個)a或b,後面跟一個c 的字元串;

一個點(‘.’)可以代表所有的單一字元,不包括”n”

如果,要比對包括”n”在内的所有單個字元,怎麼辦?

對了,用’[n.]‘這種模式.

”a.[0-9]“: 一個a加一個字元再加一個0到9的數字

”^.{3}$”: 三個任意字元結尾 .

中括号包覆的内容隻比對一個單一的字元

”[ab]“: 比對單個的 a 或者 b ( 和 “a│b” 一樣);

”[a-d]“: 比對’a’ 到’d'的單個字元 (和”a│b│c│d” 還有 “[abcd]“效果一樣); 一般我們都用[a-za-z]來指定字元為一個大小寫英文

”^[a-za-z]“: 比對以大小寫字母開頭的字元串

”[0-9]%”: 比對含有 形如 x% 的字元串

”,[a-za-z0-9]$”: 比對以逗号再加一個數字或字母結尾的字元串

你也可以把你不想要得字元列在中括号裡,你隻需要在總括号裡面使用’^’ 作為開頭 “%[^a-za-z]%” 比對含有兩個百分号裡面有一個非字母的字元串.

要點:^用在中括号開頭的時候,就表示排除括号裡的字元

  為了php能夠解釋,你必須在這些字元面前後加”,并且将一些字元轉義.

不要忘記在中括号裡面的字元是這條規路的例外—在中括号裡面, 所有的特殊字元,包括(”), 都将失去他們的特殊性質 “[*+?{}.]“比對含有這些字元的字元串.

還有,正如regx的手冊告訴我們: “如果清單裡含有 ‘]’, 最好把它作為清單裡的第一個字元(可能跟在’^'後面). 如果含有’-', 最好把它放在最前面或者最後面, or 或者一個範圍的第二個結束點[a-d-0-9]中間的‘-’将有效.

看了上面的例子,你對{n,m}應該了解了吧.要注意的是,n和m都不能為負整數,而且n總是小于m. 這樣,才能 最少比對n次且最多比對m次. 如”p{1,5}”将比對 “pvpppppp”中的前五個p

下面說說以開頭的

b 書上說他是用來比對一個單詞邊界,就是…比如’veb’,可以比對love裡的ve而不比對very裡有ve

b 正好和上面的b相反.例子我就不舉了

好,我們來做個應用:

如何建構一個模式來比對 貨币數量 的輸入

建構一個比對模式去檢查輸入的資訊是否為一個表示money的數字。我們認為一個表示money的數量有四種方式: “10000.00″ 和 “10,000.00″,或者沒有小數部分, “10000″ and “10,000″. 現在讓我們開始建構這個比對模式:

^[1-9][0-9]*$

這是所變量必須以非0的數字開頭.但這也意味着 單一的 “0″ 也不能通過測試. 以下是解決的方法:

^(0│[1-9][0-9]*)$

”隻有0和不以0開頭的數字與之比對”,我們也可以允許一個負号在數字之前:

^(0│-?[1-9][0-9]*)$

這就是: “0 或者 一個以0開頭 且可能 有一個負号在前面的數字.” 好了,現在讓我們别那麼嚴謹,允許以0開頭.現在讓我們放棄負号 , 因為我們在表示錢币的時候并不需要用到. 我們現在指定 模式 用來比對小數部分:

^[0-9]+(.[0-9]+)?$

這暗示比對的字元串必須最少以一個阿拉伯數字開頭. 但是注意,在上面模式中 “10.” 是不比對的, 隻有 “10″ 和 “10.2″ 才可以. (你知道為什麼嗎)

^[0-9]+(.[0-9]{2})?$

我們上面指定小數點後面必須有兩位小數.如果你認為這樣太苛刻,你可以改成:

^[0-9]+(.[0-9]{1,2})?$

這将允許小數點後面有一到兩個字元. 現在我們加上用來增加可讀性的逗号(每隔三位), 我們可以這樣表示:

^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$

不要忘記 ‘+’ 可以被 ‘*’ 替代 如果你想允許空白字元串被輸入話 (為什麼?). 也不要忘記反斜杆 ’’ 在php字元串中可能會出現錯誤 (很普遍的錯誤).

  現在,我們已經可以确認字元串了, 我們現在把所有逗号都去掉 str_replace(“,”, “”, $money) 然後在把類型看成 double然後我們就可以通過他做數學計算了.

  再來一個:

構造檢查email的正規表達式

在一個完整的email位址中有三個部分:

1. 使用者名 (在 ‘@’ 左邊的一切),

[email=2.'@']2.[/email],

3. 伺服器名(就是剩下那部分).

使用者名可以含有大小寫字母阿拉伯數字,句号 (‘.’), 減号(‘-’), and 下劃線 (‘_’). 伺服器名字也是符合這個規則,當然下劃線除外.

  現在, 使用者名的開始和結束都不能是句點. 伺服器也是這樣. 還有你不能有兩個連續的句點他們之間至少存在一個字元,好現在我們來看一下怎麼為使用者名寫一個比對模式:

  ^[_a-za-z0-9-]+$

現在還不能允許句号的存在. 我們把它加上:

^[_a-za-z0-9-]+(.[_a-za-z0-9-]+)*$

上面的意思就是說: “以至少一個規範字元(除了.)開頭,後面跟着0個或者多個以點開始的字元串.”

簡單化一點, 我們可以用 eregi()取代 ereg().eregi()對大小寫不敏感, 我們就不需要指定兩個範圍 “a-z” 和 “a-z” – 隻需要指定一個就可以了:

^[_a-z0-9-]+(.[_a-z0-9-]+)*$

後面的伺服器名字也是一樣,但要去掉下劃線:

^[a-z0-9-]+(.[a-z0-9-]+)*$

好. 現在隻需要用”@”把兩部分連接配接:

^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*$

  這就是完整的email認證比對模式了,隻需要調用

eregi(‘^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*$ ’,$eamil)

就可以得到是否為email了

正規表達式的其他用法

提取字元串

ereg() and eregi() 有一個特性是允許使用者通過正規表達式去提取字元串的一部分,比如說,我們想從 path/url 提取檔案名 – 下面的代碼就是你需要:

ereg(“([^\/]*)$”, $pathorurl, $regs);

echo $regs[1];

進階的代換

ereg_replace() 和 eregi_replace()也是非常有用的: 假如我們想把所有的間隔負号都替換成逗号:

ereg_replace(“[ nrt]+”, “,”, trim($str));

最後,我把另一串檢查email的正規表達式讓看文章的你來分析一下.

“^[-!#$%&'*+\./0-9=?a-z^_`a-z{|}~]+’.'@’.’[-!#$%&'*+\/0-9=?a-z^_`a-z{|}~]+.’.’[-!#$%&'*+\./0-9=?a-z^_`a-z{|}~]+$”

  如果能友善的讀懂,那這篇文章的目的就達到了.

 下面附上常用的正規表達式【摘自百度百科】

  常用的正規表達式主要有以下幾種:

  比對中文字元的正規表達式: [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-d|d-d

  評注:比對形式如 0511-4405222 或 021-87888822

  比對騰訊qq号:[1-9][0-9]{4,}

  評注:騰訊qq号從10000開始

  比對中國郵政編碼:[1-9]d(?!d)

  評注:中國郵政編碼為6位數字

  比對×××:d|d

  評注:中國的×××為15位或18位

  比對ip位址:d+.d+.d+.d+

  評注:提取ip位址時有用

  比對特定數字:

  ^[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個英文字母或者下劃線組成的字元串