8 種 B 族維生素,仁和眾久佐寧牌 B 族維生素片 100 片 9.9 元
正則表示式學習筆記
(原創內容,轉載請註明來源,謝謝)
首先,學習正則表示式,很推薦一篇部落格,http://www.cnblogs.com/deerchao/archive/2006/08/24/zhengzhe30fengzhongjiaocheng.html,deerchao寫的《正則表示式30分鐘入門教程》,看完他的文章,基本上可以在實際中使用正則表示式,本文是結合此部落格和一些其他書籍的內容的學習筆記。
一、基礎內容
我認為的基礎內容包括以下7點,掌握後可以使用正則匹配很多內容。
1、位置
正則表示式表示位置的字元有^(表示字串開始)、$(字串結束)、b(字串開始或結束)。
在明確需要匹配的位置的情況下,建議使用^、$,因為其會加快字串的匹配速度。
2、數量
正則表示式表示數量的主要有*(匹配任意次)、?(匹配0次或1次)、+(匹配1次或多次)、[](中括號內的內容匹配其中一個一次)、{m,n}(匹配m至n次,n省略則匹大於或等於m次,逗號也省略則匹配m次)。
3、字元組
字元組為使用一些特殊的方式表示一組同樣規律的內容。d表示0-9任意一個數字,
s表示任意個空白字元(空格),w表示任意大小寫字母、數字、下劃線、中文。.(點)表示換行符以外的任意內容。
字元組和數量常常組合起來使用,如匹配四位數字可以用d{4}。
4、反義
^符號用在正則的第一個位置表示字串的開始,但是用在[]內部則表示非,例如[^d]表示匹配1個不是數字的字元。其他還有W(表示非w)、D(表示非d)、S(表示s)、[^abc]表示匹配abc以外的字元。
5、轉義
轉義使用反斜槓,這個和很多程式語言相同。即\匹配,.匹配.等。
6、分支
分支符號為|,和程式語言中的||意思相似,表示或的意思。例如要匹配my和mine,可以使用m(y|ine)進行匹配。
7、分組
分組採用()(小括號)把內容放在裡面,通常分組後可以加上表示數量的詞,進行批量匹配。例如要匹配的內容是三個數字加一個字母a,一共匹配10次,可以用(d{3}a){10}。
二、進階內容
除了上述內容,正則表示式提供了一些高階的功能,讓匹配更加全面與方便。
1、捕獲
1) (?<name>exp),該含義為匹配表示式exp,並將其命名為name,後面的匹配中可以用k<name>表示匹配到的內容。
例如,(?<myname>d{4})w?k<myname>,表示把第一次匹配到的4個數字存在myname內,後面就用k<mynname>再次匹配即可。
2) 捕獲還有其他寫法,如(exp),表示不給exp取名字,該情況下會儲存在系統預設名字內,從1開始編號。例如(d)w(d{5})w1w2,表示第一次捕獲的一個數字存在1內,第二次捕獲的五個數字存在2內。
3) 因此,在正則表示式中,括號應當慎用,因為每個括號正則都會將其捕獲,並進行儲存,如果在長字串匹配的情況下,又使用了大量的括號,將佔用較多儲存空間。另外,如果不需要捕獲內容,可以使用(?:exp),表示不捕獲文字,也不進行編號。
2、零寬斷言
零寬斷言也是類似$、^等表示位置的字元,但是對該位置上的字元有一定的要求。主要有四個表達方式。
1) (?=exp),表示該位置的內容要滿足exp的要求時,匹配exp之前的內容。例如w+(?=ing),會匹配doing的do。
2) (?<=exp),表示該位置的內容要滿足exp的要求時,匹配exp之後的內容。例如w+(?<=re),會匹配reading的ading。
3) (?!exp),表示該位置的內容不是exp時,匹配exp之前的內容。例如bw+(?!ing)b,會匹配不含ing結尾的任意單詞。
4) (?<!exp),表示該位置的內容不是exp時,匹配exp之後的內容。例如bw+(?!re)b會匹配任意不是以re開頭的單詞。
上述內容中,3)、4)又稱為負向零寬斷言。
3、註釋
(?#comment)表示註釋,不會被解析,僅僅是便於其他人員檢視正則表示式。
4、懶惰匹配
1) 懶惰匹配表示匹配儘量少的內容,在匹配符後面加上一個?即可。*?表示重複任意次,但是儘可能的少重複;{10,}表示重複10次以上,但是儘可能少重複。其他數量詞加上?也一樣,表示滿足基本條件的情況下儘可能少匹配。
例如,a.*?b在字串abaab中會匹配到ab。
2) 與懶惰匹配相對應的,就是貪婪匹配,在不加?情況下,前面說的內容都是貪婪匹配。
3) 為了使程式匹配速度更快,在確定只需要懶惰匹配的情況下,需要加上?,可以最快匹配到需要的內容。
5、優先順序問題
優先順序從高到低,依次是:
1)
2) ()、(?=)、(?=)、[]
3) *、+、?、{n}、{n,}、{n,m}
4) ^、$、任意字元
5) |
三、PHP正則表示式匹配函式
1、preg_math
官方文件int preg_match ( string $pattern
, string $subject
[, array &$matches
[, int $flags
= 0 [, int $offset
= 0 ]]] )
常用到前三個引數,$pattern表示匹配的模式,$subject表示需要匹配的字串,如果提供了引數matches,它將被填充為搜尋結果。$matches[0]將包含完整模式匹配到的文字,$matches[1] 將包含第一個捕獲子組匹配到的文字,以此類推。
函式返回:pattern 的匹配次數。它的值將是0次(不匹配)或1次,因為preg_match()在第一次匹配後 將會停止搜尋。
2、preg_match_all
官方文件int preg_match_all ( string $pattern
, string $subject
[, array &$matches
[, int $flags
= PREG_PATTERN_ORDER
[, int$offset
= 0 ]]] )
前三個引數和preg_math一樣,返回完整匹配次數(可能是0),或者如果發生錯誤返回FALSE。該函式匹配成功一次後,會從匹配成功的最後一個位置開始,繼續往後匹配。
3、常用模式
preg_math和preg_math_all的$pattern,需要輸入的字串都是 ‘%exp%’,即在正則表示式的基礎上,前後加上兩個%。通常來說,不使用%,而用其他符號也可以,只需要保證前後一致即可。實際工程中,為了專案統一,最好定一個一致的號碼。
1) 忽略大小寫
$pattern = ‘%exp%i’,即在第二個%後面加一個字母i即忽略大小寫匹配。
2) 點號通配模式
點號通配模式表示元字元.(點)忽略換行。使用方法是$pattern= ‘%exp%s’
3) 多行模式
多行模式表示,當$pattern是多行內容時,如果加上$、^,該模式下,會將$、^之間的內容當成一行內容,忽略字串當中的換行n。使用方法是$pattern = ‘%exp%m’
4) 懶惰模式
類似於正則表示式的懶惰模式,使用方法是$pattern = ‘%exp%U’
5) 結尾限制模式
該模式下,結尾不能有換行,否則匹配失敗。使用方法是$pattern = ‘%exp%D’
6) 支援UTF-8轉義表達方式
如果漢字等被用UTF-8編碼,則需要開啟此模式進行匹配。使用方法是$pattern = ‘%exp%u’
四、實際應用
1、校驗
如手機號校驗,要判斷手機號是否為移動的號碼,即要確定開頭為135-139、150-151、157-159、182、183、188的手機號,表示式如下:
(?:13[4-9]|15[01789]|18[238])d{8}
2、資料安全
當給使用者提供輸入框時,使用者可能往裡面輸入js程式碼對網站進行破壞,這個稱為XSS攻擊,因此可以用正則表示式把所有的<>或者</>去掉。表示式如下:
</?[^>]+>
3、URL重定向
在Apache和Nginx中,經常需要配置url的rewrite,可以把php字尾的檔案重定向到html字尾的檔案中,這樣做便於搜尋引擎的檢索。
假設需要把test.php?name=a&page=1重定向為test_a_1.html,在apache的.htaccess中,可以如下方式:
RewriteEngine on
RewriteRule index.html index.php
RewriteRule test_([a-z]+)(d?).htmltest.php?name=$1&page=$2[NC]
NC表示忽略大小寫,rewriteengineon是開啟rewrite的意思。
五、PHP正則表示式的優化
當字串很長,需要匹配的模式串也很長的時候,需要儘可能的對正則表示式進行優化,否則會降低程式執行速度。
1、滿足匹配前提下少用|
|符號效率較低,需要逐個進行匹配,例如[abc]和[a|b|c],|會把內容分別進行匹配。
2、限定量詞優先
在確定需要匹配次數的情況下,儘量不要使用*、+、{n,}等不限定長度的量詞,否則會進行多次的查詢。
3、優先用preg_match/命中率最高的匹配項放最左側
因為其匹配到就停止,而preg_match_all會把全部內容匹配完。同樣,在多個匹配條件情況下,把最有可能命中的情況放在最左側,則匹配到就不會繼續往後匹配。
4、合理使用括號
括號會佔用儲存空間,大量匹配的情況下慎用。
5、使用PHP自帶的一些函式
1) 當可以確定需要的字串的位置時,儘量使用字串匹配函式,即str開頭的函式,匹配速度更快。
2) 需要匹配PHP的原始碼,可以安裝使用PHP自帶的Tokenizer分析函式,可以準確的分析PHP的變數、常量、類名、方法名等。
3) 解析URL時,可以用PHP自帶的parse_url()函式,該函式可以把url的型別、host、path、query等輸出。
4) 獲取HTTP頭,可以使用PHP自帶的get_headers()函式,該函式可以捕獲到HTTP頭的資訊,並用陣列方式返回。
5) 驗證郵箱資訊、URL資訊、資料型別等,均可以安裝使用PHP的filter_var函式,該函式可以使用特定的過濾器過濾一個變數。
六、驗證正則表示式的正確性
網上有很多驗證工具,我個人比較喜歡的是http://tool.lu/regex/
——written by linhxx 2017.07.05