php中正則表達式詳解

概述

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

  • 有哪些經常使用的轉義字符
  • 什麼是限定符與定位符
  • 什麼是單詞定位符
  • 特殊字符有哪些
  • 什麼是逆向引用以及怎樣使用逆向引用
  • 匹配模式
  • php中怎樣使用正則表達式
  • php中哪些方面須要用到正則
  • 怎樣進行郵箱匹配,url匹配,手機匹配
  • 怎樣使用正則替換字符串中某些字符
  • 貪婪匹配與惰性匹配區別
  • 正則表達式之回溯與固態分組
  • 正則優缺點有哪些

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

行定位符(^與$)

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

單詞定界符

咱們在查找的一個單詞的時候,如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之間的數字。ruby

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

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

限定字符 含義
零次或一次
* 零次或屢次
+ 一次或屢次
{n} n次
{n,} 至少n次
{n,m} n到m次

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

點號操做符

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

表達式中的反斜槓(\)

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

轉義字符

轉義字符主要是將一些特殊字符轉爲普通字符。而這些經常使用特殊字符有」.」,」?」、」\」等。url

指定預約義的字符集

字符 含義
\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 ( string haystack,mixedneedle [, bool $before_needle = false ]) 
    • 注1:haystack,needle是被查找的字符串。該函數區分大小寫。
    • 注2:返回值是從needle開始到最後。
    • 注3:關於$needle,若是不是字符串,被看成整形來做爲字符的序號來使用。
    • 注4:before_needle若爲true,則返回前東西。
  • stristr函數與strstr函數相同,只是它不區分大小寫
  • strpo函數 
    int strpos ( string haystack,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'; function checkStr1($str,$str2) { return strstr1($str,$str2)?true:false; } echo checkStr($str,'csdn');

解法二:使用正則 
由於咱們只須要判斷是否存在便可,因此選擇preg_match。

$str='http://blog.csdn.net/hsd2012'; $pattern='/csdn/'; function checkStr2($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 ( mixed pattern,mixedreplacement , mixed subject[,intlimit = -1 [, int &count]])串subject中,查找pattern,使用replacement 去替換,若是有limitlimitpregreplacecallbackpregreplacepregreplaceback使調callbackreplacement.1hello,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 ( string delimiter,stringstring [, int $limit ] ) 
delimiter:邊界上的分隔字符。 
string:輸入的字符串。 
limit:若是設置了 limit 參數而且是正數,則返回的數組包含最多 limit 個元素,而最後那個元素將包含 string 的剩餘部分。若是 limit 參數是負數,則返回除了最後的 -limit 個元素外的全部元素。若是 limit 是 0,則會被當作 1。

使用正則

關於經過正則表達式進行字符串分割,php提供了split、preg_split 函數。preg_split() 函數,一般是比 split() 更快的替代方案。 
array preg_split ( string pattern,stringsubject [, int limit=1[,intflags = 0 ]] )

$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’中最後一個字符w c進行下一個字符匹配時
‘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 ( string string,intstart [, int length])stringmbsubstr(stringstr , int start[,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中正則的效率,每每是咱們須要考慮的,因此在某些時候,能不用正則仍是儘可能不去用它,除非,某些場合必須用到,或是咱們可以有效減小其回溯次數。

相關文章
相關標籤/搜索