正規表示式30分鐘入門教學
#零寬斷言
跳過目錄本文目標
30分鐘內讓你明白正規表示式是什麼,並對它有一些基本的了解,讓你可以在自己的程式或網頁裡使用它。 如何使用本教學最重要的是-請給我30分鐘,如果你沒有使用正規表示式的經驗,請不要試圖在30秒內入門-除非你是超人:)別被下面那些複雜的表達式嚇倒,只要跟著我一步一步來,你會發現正規表示式其實並沒有你想像中的那麼困難。當然,如果你看完了這篇教學之後,發現自己明白了很多,卻又幾乎什麼都記不得,那也是很正常的——我認為,沒接觸過正規表達式的人在看完這篇教程後,能把提到的語法記住80%以上的可能性為零。這裡只是讓你明白基本的原理,以後你還需要多練習,多使用,才能熟練正規表示式。 除了作為入門教學之外,本文也試圖成為可以在日常工作中使用的正規表示式語法參考手冊。就作者本人的經驗來說,這個目標還是完成得很好的──你看,我自己也沒能把所有的東西記下來,不是嗎? 清除格式 文字格式約定:專業術語 元素字元/語法格式 正規表示式 正規表示式中的一部分(用於分析)
對其進行比對的來源字符字串
對正規表示式或其中一部分的說明#隱藏邊註 本文右邊有一些註釋,主要是用來提供一些相關訊息,或是給沒有程式設計師背景的讀者解釋一些基本概念,通常可以忽略。 正規表示式到底是什麼東西? 字元是電腦軟體處理文字時最基本的單位,可能是字母,數字,標點符號,空格,換行符,漢字等等。 字串
是0個或更多字元的序列。文字也就是文字,字串。說某個字串
符合######某個正規表示式,通常是指這個字串裡有一部分(或幾部分分別)能滿足表達式給出的條件。 ######在寫處理字串的程式或網頁時,常常會有尋找符合某些複雜規則的字串的需求。 ######正規表示式######就是用來描述這些規則的工具。換句話說,正規表示式就是記錄文字規則的程式碼。 ###很可能你使用過Windows/Dos下用於檔案尋找的通配符(wildcard),也就是##*和?。如果你想找某個目錄下的所有的Word文件的話,你會搜尋*.doc。在這裡,*會被解釋成任意的字串。和通配符類似,正規表示式也是用來進行文字比對的工具,只不過比起通配符,它能更精確地描述你的需求——當然,代價就是更複雜——例如你可以寫一個正規表示式,用來找出所有以0開頭,後面跟著2-3個數字,然後是一個連字號“-”,最後是7或8位數字的字串(像010-12345678或0376-7654321#)。
入門學習正規表示式的最好方法是從例子開始,理解例子之後再自己對例子進行修改,實驗。下面給了不少簡單的例子,並對它們作了詳細的說明。 假設你在一篇英文小說裡尋找hi,你可以使用正規表示式hi。
這幾乎是最簡單的正規表示式了,它可以精確地匹配這樣的字串:由兩個字元組成,前一個字元是h,後一個是i。通常,處理正規表示式的工具會提供一個忽略大小寫的選項,如果選取了這個選項,它可以符合hi,HI ,Hi,hI這四個情況中的任一種。
不幸的是,很多單字包含hi這兩個連續的字符,像是him,history,high等等。用hi來找出的話,這裡邊的hi也會被找出來。如果要精確地找出hi這個字的話,我們應該使用/bhi/b。
/b是正規表示式規定的一個特殊代碼(好吧,某些人叫它元字符,metacharacter ),代表單字的開頭或結尾,也就是單字的分界處。雖然通常英文的單字是由空格,標點符號或換行來分隔的,但是/b並不會符合這些單字分隔字元中的任何一個,它只符合一個位置。
如果需要更精確的說法,/b匹配這樣的位置:它的前一個字元和後一個字元不全是(一個是,一個不是或不存在)/w。
假如你要找的是hi後面不遠處跟著一個Lucy#,你應該用/bhi/b.*/bLucy /b。
這裡,.是另一個元字符,匹配#除了換行符以外的任意字符。 *同樣是元字符,不過它代表的不是字符,也不是位置,而是數量-它指定*前邊的內容可以連續重複使用任意次以使整個表達式得到匹配。因此,.*連在一起就意味著任意數量的不包含換行的字元#。現在/bhi/b.*/bLucy/b的意思就很明顯了:先是一個單字hi,然後是任意個任意字元(但不能是換行),最後是Lucy這個字。
換行符就是'/n',ASCII編碼為10(十六進位0x0A)的字元。如果同時使用其它元字符,我們就能建構出功能更強大的正規表示式。例如下面這個範例:
0/d/d-/d/d/d/d/d/d/d/d符合這樣的字串: 以0開頭,然後是兩個數字,然後是一個連字號“-”,最後是8個數字(也就是中國的電話號碼。當然,這個例子只能匹配區號為3位的情形)。
這裡的/d是個新的元字符,符合一位數字(0,或1,或2,或…) 。 -不是元字符,只符合它本身-連字符(或減號,或是中橫線,或隨你怎麼稱呼它)。
為了避免那麼多煩人的重複,我們也可以這樣寫這個表達式:0/d{2}-/d{8}。 這裡/d後面的{2}#({8})的意思是前面/d必須連續重複符合2次(8次)。
其它可用的測試工具:
RegexBuddy
如果你不覺得正規表示式很難讀寫的話,要嘛你是個天才,要嘛,你不是地球人。正規表示式的語法很令人頭疼,即使對經常使用它的人來說也是如此。由於難於讀寫,容易出錯,所以找工具對正規表示式進行測試是必要的。
不同的環境下正規表示式的一些細節是不相同的,本教程介紹的是微軟.Net Framework 2.0下正則表達式的行為,所以,我向你介紹一個.Net下的工具Regex Tester。首先你確保已經安裝了.Net Framework 2.0,然後下載Regex Tester。這是個綠色軟體,下載完後開啟壓縮包,直接運行RegexTester.exe就可以了。
下面是Regex Tester運行時的截圖:
#現在你已經知道幾個很有用的元字元了,如/b,.,##*,還有/d.正規表示式裡還有更多的元字符,例如/s符合任意的空白符,包括空格,製表符(Tab),換行符,中文全角空格等。 /w符合字母或數字或底線或漢字等。
對中文/漢字的特殊處理是由.Net提供的正規表示式引擎支援的,其它環境下的具體情況請查看相關文件。 下面來看看更多的例子:/ba/w*/b匹配以字母a開頭的單字-先是某個單字開始處(/b),然後是字母a,然後是任意數量的字母或數字(/w*),最後是單字結尾(#/b#)。
好吧,現在我們說說正規表示式裡的單字是什麼意思:就是不少於一個的連續的/w。不錯,這與學習英文時要背的成千上萬個同名的東西的確關係不大:)
#/d+匹配 #1個或更多連續的數字。這裡的+是和*類似的元字符,不同的是##* #符合重複任意次(可能是0次),而+則符合重複1次或更多次。
/b/w{6}/b 符合#剛好6個字元的單字。 正規表示式引擎通常會提供一個「測試指定的字串是否符合一個正規表示式」的方法,如JavaScript裡的RegExp.test()方法或.NET裡的Regex.IsMatch()方法。這裡的匹配是指是字串裡有沒有符合表達式規則的部分。如果不使用^和$的話,對於/d{5,12}而言,使用這樣的方法就只能保證字串裡包含5到12連續位數字,而不是整個字串就是5到12位數字。 元字元^(和數字6在同一個鍵位上的符號)和$都匹配一個位置,這和/b有點類似。 ^符合你要用來尋找的字串的開頭,$符合結尾。這兩個程式碼在驗證輸入的內容時非常有用,例如一個網站如果要求你填寫的QQ號必須為5位到12位數字時,可以使用:^/d{5,12} $。 這裡的{5,12}和前面介紹過的{2}是類似的,只不過{2}符合只能不多重複2次,{5,12} 則是重複的次數不能少於5次,不能多於12次,否則都不符合。 因為使用了^和$,所以輸入的整個字串都要用來和/d{5,12}來匹配,也就是說整個輸入#必須是5到12個數字,因此如果輸入的QQ號能符合這個正規表示式的話,那就符合要求了。 和忽略大小寫的選項類似,有些正規表示式處理工具還有一個處理多行的選項。如果選取了這個選項,^和$#的意義就變成了符合行的開始處和結束處。 如果你想找出元字元本身的話,例如你找#.,或*,就出現了問題:你沒辦法指定它們,因為它們會被解釋成別的意思。這時你就得使用/來取消這些字元的特殊意義。因此,你應該使用/.和/*#。當然,要找/本身,你也得用//. 例如:unibetter/.com符合unibetter.com#,C://Windows##符合 C:/Windows。 *,+##,{2},{5,12}這幾個符合重複的方式了。以下是正規表示式中所有的限定符(指定數量的程式碼,例如*,{5,12}等): 以下是一些使用重複的範例: Windows/d+#比Windows後面跟1個或更多數字 ^/w+符合#一行的第一個單字(或整個字串的第一個單字,具體要匹配哪個意思得看選項設定) 要想找出數字,字母或數字,空白是很簡單的,因為已經有了對應這些字符集合的元字符,但是如果你想匹配沒有預定義元字符的字符集合(比如元音字母a,e,i,o,u),應該怎麼辦? 很簡單,你只需要在方括號裡列出它們就行了,像[aeiou]就符合任何一個英文元音字母,[.?!]符合#標點符號(.或?或!)#。 我們也可以輕鬆地指定一個字元範圍,像是[0-9]代表的含意與/d就是完全一致的:一位數字#;同理[a-z0-9A-Z_ ]也完全等同於/w(如果只考慮英文的話)。 下面是一個更複雜的表達式:/(?0/d{2}[) -]?/d{8}。 「(」和「)」也是元字符,後面的分組節會提到,所以在這裡需要使用轉義。 這個表達式可以符合幾種格式的電話號碼,像是(010)88886666,或022-22334455,或02912345678等。我們對它做一些分析:首先是一個轉義字元/(,它能出現0次或1次(? #),然後是一個0,後面跟著2個數字(#/d{2}),然後是 )或-或空格中的一個,它出現1次或不出現( ?),最後是8個數字(/d{8})。 不幸的是,剛才那個表達式也能符合010)12345678或#(022 -87654321這樣的「不正確」的格式。 分枝條件指的是有幾種規則,如果滿足其中任一種規則都應該當成匹配,具體方法是用|##把不同的規則分隔開。 {7}這個表達式能符合兩種以連字號分隔的電話號碼:一種是三位區號,8位元本地號(如010-12345678),一種是4位元區號,7位元本地號(0376-2233445)。 8}|0/d{2}[- ]?/d{8} 這個運算式符合3位區號的電話號碼,其中區號可以用小括號括起來,也可以不用,區號與本地號間可以用連字號或空格間隔,也可以沒有間隔。 # /d{5}-/d{4}|/d{5}這個表達式用來符合美國的郵遞區號。美國郵編的規則是5位數,或是用連字間隔的9位數字。之所以要舉這個例子是因為它能說明一個問題:使用分枝條件時,要注意各個條件的順序。如果你把它改成/d{5}|/d{5}-/d{4}的話,那麼就只會配對5位的郵編(以及9位郵編的前5位)。原因是匹配分枝條件時,將會從左到右地測試每個條件,如果滿足了某個分枝的話,就不會去再管其它的條件了。 我們已經提到了怎麼重複單一字元(直接在字元後面加上限定符就行了);但如果想要重複多個字元又該怎麼辦?你可以用小括號來指定子表達式(也叫做分組),然後你就可以指定這個子表達式的重複次數了,你也可以對子表達式進行其它一些操作(後面會有介紹)。 (/d{1,3}/.){3}/d{1,3}是一個簡單的IP位址匹配表達式。要理解這個表達式,請按下列順序分析它:/d{1,3}#符合1到3位的數字,(/d{1,3}/.){3}匹配三位數字加上一個英文句號(這個整體也就是這個分組)重複3次,最後再加上一個一到三位的數字( /d{1,3})。 IP位址中每個數字都不能大於255,大家千萬不要被《24》第三季的編劇給忽悠了… #不幸的是,它也將匹配256.300.888.999這種不可能存在的IP位址。如果能使用算術比較的話,或許能簡單地解決這個問題,但是正則表達式中並不提供關於數學的任何功能,所以只能使用冗長的分組,選擇,字符類來描述一個正確的IP地址:((2[0-4]/d|25[0-5]|[01]?/d/d?)/.){3}(2[0-4]/d|25 [0-5]|[01]?/d/d?)。 理解這個表達式的關鍵是理解2[0-4]/d|25[0-5]|[01]?/d/d?,這裡我就不細說了,你自己應該可以分析得出來它的意義。
############符合字串的結束###################
程式碼
#說明
#.
符合換行符號以外的任意字元
/w
符合字母或數字或底線或漢字
/s
符合任意的空白符
/d
匹配數字
/b ##^#對單字的開始或結束
#$
符合字串的開始
字元轉義
############### ###
程式碼/語法
#說明
*
重複零次或更多
#+
重複一次或更多
?
重複零次或一次
#{n} 重複n次
{n,} 重複n次或更多
{n,m} 重複n到m次 字符類別
分枝條件
分組
以上是正規表示式入門教程的詳細內容。更多資訊請關注PHP中文網其他相關文章!