php中正則表達式詳解

概述

正則表達式是一種描述字符串結果的語法規則,是一個特定的格式化模式,可以匹配、替換、截取匹配的字符串。常用的語言基本上都有正則表達式,如JavaScript、java等。其實,只有了解一種語言的正則使用,其他語言的正則使用起來,就相對簡單些。文本主要圍繞解決下面問題展開。

有哪些常用的轉義字符

什么是限定符與定位符

什么是單詞定位符

特殊字符有哪些

什么是逆向引用以及怎樣使用逆向引用

匹配模式

php中怎樣使用正則表達式

php中哪些方面需要用到正則

怎樣進行郵箱匹配,url匹配,手機匹配

怎樣使用正則替換字符串中某些字符

貪婪匹配與惰性匹配區別

正則表達式之回溯與固態分組

正則優缺點有哪些

正則表達式的基本知識匯總

行定位符(^與$)

行定位符是用來描述字符串的邊界。“$”表示行結尾“^”表示行開始如"^de",表示以de開頭的字符串"de$",表示以de結尾的字符串。

單詞定界符

我們在查找的一個單詞的時候,如an是否在一個字符串”gril and body”中存在,很明顯如果匹配的話,an肯定是可以匹配字符串“gril and body”匹配到,怎樣才能讓其匹配單詞,而不是單詞的一部分呢?這時候,我們可以是喲個單詞定界符\b。

\ban\b 去匹配”gril and body”的話,就會提示匹配不到。

當然還有一個大寫的\B,它的意思,和\b正好相反,它匹配的字符串不能使一個完整的單詞,而是其他單詞或字符串中的一部分。如\Ban\B。

選擇字符(|) ,表示或

選擇字符表示或的意思。如Aa|aA,表示Aa或者是aA的意思。注意使用”[]”與”|”的區別,在于”[]”只能匹配單個字符,而”|”可以匹配任意長度的字符串。在使用”[]”的時候,往往配合連接字符”-“一起使用,如[a-d],代表a或b或c或d。

排除字符,排除操作

正則表達式提供了”^”來表示排除不符合的字符,^一般放在[]中。如[^1-5],該字符不是1~5之間的數字。

限定符(?*+{n,m})

限定符主要是用來限定每個字符串出現的次數。

限定字符含義

?零次或一次

*零次或多次

+一次或多次

{n}n次

{n,}至少n次

{n,m}n到m次

如(D+)表示一個或多個D

點號操作符

匹配任意一個字符(不包含換行符)

表達式中的反斜杠(\)

表達式中的反斜杠有多重意義,如轉義、指定預定義的字符集、定義斷言、顯示不打印的字符。

轉義字符

轉義字符主要是將一些特殊字符轉為普通字符。而這些常用特殊字符有”.”,”?”、”\”等。

指定預定義的字符集

字符含義

\d任意一個十進制數字[0-9]

\D任意一個非十進制數字

\s任意一個空白字符(空格、換行符、換頁符、回車符、字表符)

\S任意一個非空白字符

\w任意一個單詞字符

\W任意個非單詞字符

###顯示不可打印的字符

字符含義

\a報警

\b退格

\f換頁

\n換行

\r回車

\t字表符

括號字符()

在正則表達式中小括號的作用主要有:

改變限定符如(|、* 、^)的作用范圍

如(my|your)baby,如果沒有”()”,|將匹配的是要么是my,要么是yourbaby,有了小括號,匹配的就是mybaby或yourbaby。

進行分組,便于反向引用

反向引用

反向引用,就是依靠子表達式的”記憶”功能,匹配連續出現的字串或是字符。如(dqs)(pps)\1\2,表示匹配字符串dqsppsdqspps。在下面php應用中,我將詳細展開學習反向引用。

模式修飾符

模式修飾符的作用是設定模式,也就是正則表達式如何解釋。php中主要模式如下表:

修飾符說明

i忽略大小寫

m多文本模式

s單行文本模式

x忽略空白字符

正則表達式在php中應用

php中字符串匹配

所謂的字符串匹配,言外之意就是判斷一個字符串中,是否包含或是等于另一個字符串。如果不使用正則,我們可以使用php中提供了很多方法進行這樣的判斷。

不使用正則匹配

strstr函數

string strstr ( stringhaystack,mixedneedle [, bool $before_needle = false ])

注1:haystack是當事字符串,needle是被查找的字符串。該函數區分大小寫。

注2:返回值是從needle開始到最后。

注3:關于$needle,如果不是字符串,被當作整形來作為字符的序號來使用。

注4:before_needle若為true,則返回前東西。

stristr函數與strstr函數相同,只是它不區分大小寫

strpo函數

int strpos ( stringhaystack,mixedneedle [, int $offset = 0 ] )

注1:可選的 offset 參數可以用來指定從 haystack 中的哪一個字符開始查找。返回的數字位置是相對于 haystack 的起始位置而言的。

stripos -查找字符串首次出現的位置(不區分大小定)

strrpos -計算指定字符串在目標字符串中最后一次出現的位置

strripos -計算指定字符串在目標字符串中最后一次出現的位置(不區分大小寫

使用正則進行匹配

在php中,提供了preg_math()和preg_match_all函數進行正則匹配。關于這兩個函數原型如下:

int preg_match|preg_match_all (string$pattern ,string$subject [, array &$matches [,int$flags =0 [,int$offset =0 ]]] )

搜索subject與pattern給定的正則表達式的一個匹配.

pattern:要搜索的模式,字符串類型。

subject :輸入字符串。

matches:如果提供了參數matches,它將被填充為搜索結果。matches[0]將包含完整模式匹配到的文本,matches[1]將包含第一個捕獲子組匹配到的文本,以此類推。

flags:flags可以被設置為以下標記值:PREG_OFFSET_CAPTURE 如果傳遞了這個標記,對于每一個出現的匹配返回時會附加字符串偏移量(相對于目標字符串的)。 注意:這會改變填充到matches參數的數組,使其每個元素成為一個由 第0個元素是匹配到的字符串,第1個元素是該匹配字符串 在目標字符串subject中的偏移量。

offset:通常,搜索從目標字符串的開始位置開始。可選參數 offset 用于 指定從目標字符串的某個未知開始搜索(單位是字節)。

返回值:preg_match()返回 pattern 的匹配次數。 它的值將是0次(不匹配)或1次,因為 preg_match()在第一次匹配后 將會停止搜索。 preg_match_all()不同于此,它會一直搜索subject直到到達結尾。 如果發生錯誤 preg_match()返回 FALSE。

實例

實例1

判斷字符串”http://blog.csdn.net/hsd2012“中是否包含csdn?

解法一(不適用正則):

如果不適用正則,我們使用strstr或者strpos中任意一個都可以,在此,我將使用strstr函數,代碼如下:

$str='http://blog.csdn.net/hsd2012';functioncheckStr1($str,$str2){return strstr1($str,$str2)?true:false;}echo checkStr($str,'csdn');

解法二:使用正則

因為我們只需要判斷是否存在即可,所以選擇preg_match。

$str='http://blog.csdn.net/hsd2012';$pattern='/csdn/';functioncheckStr2($str,$str2){return preg_match($str2,$str)?true:false;}echo checkStr2($str,$pattern);

實例2(考察單詞定界符

判斷字符串”I am a good boy”中是否包含單詞go

首先判斷是單詞,而不是字符串,因此比較的時候,需要比較是否包含’ go ‘,即在字符串go前后有一個空格。

解析:如果使用非正則比較,只需要調用上面的checkStr1()函數即可,注意,第二個參數前后要加一個空格,即’ go ‘。如果使用正則,

我們可以考慮使用單詞定界符\b,那么$pattern=’/\bgo\b/’;然后調用checkStr2函數即可.

例3(考察反向引用)

判斷字符串”I am a good boy”中是否包含3個相同的字母

解析:此時,如果我們不使用正則,將會很難判斷,因為字母太多了,我們不可能去將所有字母分別與該字符串比較,那樣工作量也比較大。這時候涉及到了正在的反向引用。在php正則表達式中,通過\n,來表示第n次匹配到的結果。如\5代表第五次匹配到的結果。那么本題的$pattern='/(\w).*\1.*\1/';

主要注意的是,在使用反向匹配的時候都需要使用(),反向匹配時,匹配()里面出現的字符或字符串。

php中字符串替換

不使用正則

php中當替換字符串的時候,如果不適用正則,我們通常使用substr、mb_substr、str_replace、substr_replace關于這幾個函數區別如下表。

函數符功能描述

str_replace(find,replace,string,count)使用一個字符串替換字符串中的另一些字符。find 必需。規定要查找的值。replace 必需。規定替換 find 中的值的值。string 必需。規定被搜索的字符串。count 可選。一個變量,對替換數進行計數。

substr_replace(string,replacement,start,length)把字符串的一部分替換為另一個字符串。適合用于替換自定位置的字符串。string 必需。規定要檢查的字符串。replacement 必需。規定要插入的字符串。start 必需。規定在字符串的何處開始替換。

使用正則

如果使用正則替換,php中提供了preg_replace _callback和preg_replace 函數,preg_replace 原型如下:

mixed preg_replace ( mixedpattern,mixedreplacement , mixedsubject[,intlimit = -1 [, int &count]])函數功能描述:在字符串subject中,查找pattern,然后使用replacement 去替換,如果有limit則代表限制替換limit次。pregreplacecallback與pregreplace功能相識,不同的是pregreplaceback使用一個回調函數callback來代替replacement.?例1將字符串”hello,中國”中的hello替換為′你好′;如果不是用正則:str=’hello,中國’;

str=strreplace(′hello′,′你好′,str)

或是使用str=substrreplace(str,’你好’,0,5)

使用正則

pattern=′/hello/′;str=preg_replace (pattern,′你好′,str);

- 例2

去除字符串”gawwenngeeojjgegop”中連續相同的字母

$str='gawwenngeeojjgegop';$pattern='/(.)\1/';$str=preg_replace($pattern,'',$str);

解析:當然這樣可能會遇到,當第一次去除了重復了字符串后,又出來重復的字符串。如字符串味’gewwenngeeojjgegop’,針對這中問題,當然,這樣的話,通過判斷,繼續替換下去。

例3

將字符串中”age13gegep3iorji65k65k”;中出現的連續兩個數字改為第二個數字,如字符串中13被改為3

$str='age13gegep3iorji65k65k';$pattern='/(\d)(\d)/';$str=preg_replace($pattern,'$2',$str);

解析:$n在正則表達式外使用反向引用。n代表第幾次匹配到的結果。

php中字符串分割

不適用正則

php提供了explode函數去分割字符串,與其對應的是implode。關于explode原型如下:

array explode ( stringdelimiter,stringstring [, int $limit ] )

delimiter:邊界上的分隔字符。

string:輸入的字符串。

limit:如果設置了 limit 參數并且是正數,則返回的數組包含最多 limit 個元素,而最后那個元素將包含 string 的剩余部分。如果 limit 參數是負數,則返回除了最后的 -limit 個元素外的所有元素。如果 limit 是 0,則會被當做 1。

使用正則

關于通過正則表達式進行字符串分割,php提供了split、preg_split 函數。preg_split() 函數,通常是比 split() 更快的替代方案。

array preg_split ( stringpattern,stringsubject [, intlimit=?1[,intflags = 0 ]] )

例題

將字符串 ‘http://blog.csdn.net/hsd2012/article/details/51152810‘按照’/’進行分割

解法一:

$str='http://blog.csdn.net/hsd2012/article/details/51152810';$str=explode('/',$str);

解法二:

$str='http://blog.csdn.net/hsd2012/article/details/51152810';$pattern='/\//';/*因為/為特殊字符,需要轉移*/$str=preg_split ($pattern,$str);

php中貪婪匹配與惰性匹配

貪婪匹配:就是匹配盡可能多的字符。

比如,正則表達式中m.*n,它將匹配最長以m開始,n結尾的字符串。如果用它來搜索manmpndegenc的話,它將匹配到的字符串是manmpndegen而非man。可以這樣想,當匹配到m的時候,它將從后面往前匹配字符n。

懶惰匹配:就是匹配盡可能少的字符。

有的時候,我們需要并不是去貪婪匹配,而是盡可能少的去匹配。這時候,就需要將其轉為惰性匹配。怎樣將一個貪婪匹配轉為惰性匹配呢?只需要在其后面添加一個”?”即可。如m.*?n將匹配manmpndegenc,匹配到的字符串是man。

函數符描述

*?零次或多次,但盡可能少的匹配

+?一次或多次,但盡可能少的匹配

??0次或1次,但盡可能少的匹配

{n,}?至少n次,但盡可能少的匹配

{n,m}?n到m次 ,但盡可能少的匹配

php正則表達式之回溯與固態分組

回溯

首先我們需要清楚什么是回溯,回溯就像是在走岔路口,當遇到岔路的時候就先在每個路口做一個標記。如果走了死路,就可以照原路返回,直到遇見之前所做過的標記,標記著還未嘗試過的道路。如果那條路也走不能,可以繼續返回,找到下一個標記,如此重復,直到找到出路,或者直到完成所有沒有嘗試過的路。首先我們看例題

$str='aageacwgewcaw';$pattern='/a\w*c/i';$str=preg_match($pattern,$str);

看到上面的程序,可能都清楚是什么意思,就是匹配$str是否包含這樣一個由”a+0個或多個字母+c”不區分大小寫的字符串。但是至于程序怎樣去匹配的呢?匹配的過程中,回溯了多少次呢?

匹配過程接下來操作描述

‘a\w*c’中a匹配到’aageacwgewcaw’中第一個字符a\w進行下一個字符匹配

因為\w是貪婪匹配,會一直匹配到’aageacwgewcaw’中最后一個字符wc進行下一個字符匹配時

‘a\w*c’中c發現沒有可以匹配的于是\w匹配進行第一次回溯,匹配到倒數第二個字符a

‘a\w*c’中c發現還是沒有可以匹配的于是\w匹配進行第二次回溯,匹配到倒數第三個字符c

‘a\w*c’中c匹配成功匹配結束返回結果

現在,如果我們將pattern改為pattern=’/a\w*?c/i’;又會回溯多少次呢?正確答案是回溯四次。

固態分組

固態分組,目的就是減少回溯次數, 使用(?>…)括號中的匹配時如果產生了備選狀態,那么一旦離開括號便會被立即 引擎拋棄掉。舉個典型的例子如: ‘\w+:’這個表達式在進行匹配時的流程是這樣的,會優先去匹配所有的符合\w的字符,假如字符串的末尾沒有’:’,即匹配沒有找到冒號,此時觸發回溯機制,他會迫使前面的\w+釋放字符,并且在交還的字符中重新嘗試與’:’作比對。但是問題出現在這里: \w是不包含冒號的,顯然無論如何都不會匹配成功,可是依照回溯機制,引擎還是得硬著頭皮往前找,這就是對資源的浪費。所以我們就需要避免這種回溯,對此的方法就是將前面匹配到的內容固化,不令其存儲備用狀態!,那么引擎就會因為沒有備用狀態可用而只得結束匹配過程。大大減少回溯的次數。

如下代碼,就不會進行回溯:

$str='nihaoaheloo';$pattern='/(?>\w+):/';$rs=preg_match($pattern,$str);

當然有的時候,又需慎用固態分組,如下,我要檢查$str中是否包含以a結尾的字符串,很明顯是包含的,但是因為使用了固態分組,反而達不到我們想要的效果

$str='nihaoahelaa';$pattern1='/(?>\w+)a/';$pattern2='/\w+a/';$rs=preg_match($pattern1,$str);//0$rs=preg_match($pattern2,$str);//1

php中其他常用字符串操作函數

字符串截取截取

string substr ( stringstring,intstart [, intlength])stringmbsubstr(stringstr , intstart[,intlength = NULL [, string $encoding = mb_internal_encoding() ]] )

字符串中大小寫轉換

strtoupper

strtolower

ucfirst

ucwords

字符串比較

-strcmp、strcasecmp、strnatcmp

字符串過濾

字符串翻轉

strrev($str);

字符串隨機排序

string str_shuffle ( string $str )

補充

怎樣進行郵箱匹配,url匹配,手機匹配

使用preg_match函數進行匹配,以下內容從TP中復制而來。

郵箱驗證

pattern=′/\w+([?+.]\w+)?@\w+([?.]\w+)?\.\w+([?.]\w+)?/’;

url匹配

pattern='/^http(s?):\/\/(?:[A-za-z0-9-]+\.)+[A-za-z]{2,4}(:\d+)?(?:[\/\?#][\/=\?%\-&~`@[\]\':+!\.#\w]*)?/’;

手機驗證

pattern=′/1[3458]\d10/’;

php中正則的優缺點

php中正則在某些時候,能幫我們解決php函數很多困難的匹配或是替換。然后php中正則的效率,往往是我們需要考慮的,所以在某些時候,能不用正則還是盡量不去用它,除非,某些場合必須用到,或是我們能夠有效減少其回溯次數。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容