1. 程式人生 > 其它 >PHP之深入學習正則表示式

PHP之深入學習正則表示式

技術標籤:PHPphp正則表示式

目錄



個人實驗梳理出來的正則,深刻理解建議讀者動手實驗。

x01 基本語法

一個完整的正則表示式由兩部分構成:元字元和普通字元。元字元就是具有特殊含義的字元,如“.”和“?”。普通字元就是僅指代自身語義的普通文字,如數字、字母等。一般情況下,正則表示式都被放在定界符內中,如“/”,避免與其他字串混淆。

1.行定界符

行定界符描述一行字串的邊界。
^:表示行開始
$:表示行結尾
【例1】
定義一個被操作字串"html、htm",一個正則表示式’/^htm/’,然後呼叫preg_match()函式執行匹配,匹配結果儲存於$matches變數中,輸出顯示匹配結果及其坐在位置。

<?php
    $subject = "html、htm";
    $pattern = '/^htm/';  //匹配開始位置的“htm”字串
    preg_match($pattern,$subject,$matches,PREG_OFFSET_CAPTURE);
    print_r
($matches); ?>

輸出結果:
在這裡插入圖片描述

$pattern = '/htm$/';  //匹配結尾的“htm”字串

輸出結果:
在這裡插入圖片描述

2.單詞定界符

單詞定界符描述一個單詞的邊界。
\b:表示單詞邊界
\B:表示非單詞邊界
【例1】
使用\b定界符匹配一個完整的“htm”。

<?php
    $subject = "html、hm、htm";
    $pattern = '/\bhtm\b/';
    preg_match($pattern,$subject,$matches,PREG_OFFSET_CAPTURE);
    print_r($matches);
?>

輸出結果:
在這裡插入圖片描述

$pattern = '/\bhtm/';

輸出結果:
在這裡插入圖片描述

$pattern = '/htm\b/';

輸出結果:
在這裡插入圖片描述

3.字元類

字元類是一個字元列表。可以使用字元類指定字元列表以匹配正則表示式中的位置。使用[]定義字元類。
【例1】
定義正則 ml、mL、Ml、ML的字元類。

<?php
    $subject = "html、hm、htm";
    $pattern = '/[mM][lL]/';
    preg_match($pattern,$subject,$matches,PREG_OFFSET_CAPTURE);
    print_r($matches);
?>

輸出結果:
在這裡插入圖片描述

4.選擇符

選擇符類似字元類,可以實現選擇字元的匹配模式。使用“|”可以定義選擇匹配模式,類似PHP運算中的邏輯或。
【例1】
字元模式可以匹配“h”,也可以匹配”Html“。

<?php
    $subject = "Html、html、hm、htm";
    $pattern = '/h|Html/';
    preg_match($pattern,$subject,$matches,PREG_OFFSET_CAPTURE); 
    print_r($matches);
?>

輸出結果:
在這裡插入圖片描述

5.範圍符

使用字元類需要列舉所有可選字元,當可選字元比較多時就比較麻煩。不過在字元類中可以用連字元“-”定義字元範圍。

<?php
    $subject = "Html、html、hm、htm";
    $pattern = '/[a-z]/';
    preg_match($pattern,$subject,$matches,PREG_OFFSET_CAPTURE); 
    print_r($matches);
?>

輸出結果:
在這裡插入圖片描述
主要用於定義多個字元類,匹配任意指定範圍的字元。

$pattern = '/[A-Z]/';  //匹配任意一個小寫字母
$pattern = '/[0-9]/';  //匹配任意一個數字
$pattern = '/[\u4e00-\u9fa5]/';  //匹配任意中文字元
$pattern = '/[\x00-\xff]/';  //匹配任意單位元組字元

6.排除符

除了範圍符外,排除符“^“放到方括號內,即表示排除字元列表。類似PHP運算中的邏輯非。

<?php
    $subject = "Html、html、hm、htm";
    $pattern = '/[^a-z]/';
    preg_match($pattern,$subject,$matches,PREG_OFFSET_CAPTURE); 
    print_r($matches);
?>

輸出結果:
在這裡插入圖片描述

7.限定符

用來指定正則表示式的一個給定字元、字元類或子表示式必須要出現多少次才能滿足匹配。
* 匹配0次或多次

<?php
    $subject = "gooooogle";
    $pattern = '/go*/';
    preg_match($pattern,$subject,$matches,PREG_OFFSET_CAPTURE); 
    print_r($matches);
?>

輸出結果:
在這裡插入圖片描述
+ 匹配1次或多次

$pattern = '/go+/';

輸出結果:
在這裡插入圖片描述
? 匹配0次或1次

$pattern = '/go?/';

輸出結果:
在這裡插入圖片描述
{n} 匹配前一個內容的重複次數為n次

$pattern = '/go{2}/';

輸出結果:
在這裡插入圖片描述
{n,} 匹配前一個內容的重複次數大於等於n次

$pattern = '/go{2,}/';

輸出結果:
在這裡插入圖片描述
{n,m} 匹配前一個內容的重複次數m次到n次

$pattern = '/go{2,4}/';

輸出結果:
在這裡插入圖片描述
注意:除了{n}之外,所有限定符都具有貪婪性,因為它們會盡可能多的匹配字元,只有在字元後面加上?就可以實現非貪婪模式或最小匹配。

$pattern = '/goo*?/';

輸出結果:
在這裡插入圖片描述

$pattern = '/go{2,4}?/';

輸出結果:
在這裡插入圖片描述

8.任意字元

點號(.)能夠匹配除換行符\n之外的任何單字元。如果要匹配點號(.)自己,需要使用\進行轉義。

<?php
    $subject = "gooo.oogle";
    $pattern = '/o.{1,6}/';
    preg_match($pattern,$subject,$matches,PREG_OFFSET_CAPTURE); 
    print_r($matches);
?>

輸出結果:
在這裡插入圖片描述

$pattern = '/\..*/';

輸出結果:
在這裡插入圖片描述

9.轉義字元

轉義字元”\“能偶將特殊字元變為普通的字元,如.、*、^、$等,其功能與PHP字串中的轉義字元類似。
【例1】
為了匹配IP地址,使用轉義符號”\“把元字元(.)進行轉義,然後配合限定符匹配IP字串。

<?php
    $subject = "127.0.0.1";
    $pattern = '/([0-9]{1,3}\.?){4}/';
    preg_match($pattern,$subject,$matches,PREG_OFFSET_CAPTURE); 
    print_r($matches);
?>

輸出結果:
在這裡插入圖片描述

10.反斜槓

反斜槓”\“除了能夠轉義以外,還具備其他功能。
1.定義非列印字元

\f:匹配一個換頁符
\n:匹配一個換行符
\r:匹配一個回車符
\s:匹配任何空白符,包括空格、製表符、換頁符等
\S:匹配任何非空白符
\t:匹配一個製表符
\v:匹配一個垂直製表符
<?php
    $subject = "goo   ooogle";
    $pattern = '/\soo\S*/';
    preg_match($pattern,$subject,$matches,PREG_OFFSET_CAPTURE); 
    print_r($matches);
?>

輸出結果:
在這裡插入圖片描述
2.預定義字符集

\d:匹配一個數字字元
\D:匹配一個非數字字元
\s:匹配任何空白符,包括空格、製表符、換頁符等
\S:匹配任何非空白符
\w:匹配任何下劃線的任何單詞數字字元
\W:匹配 任何非單詞數字字元
<?php
    $subject = "goo123oogle";
    $pattern = '/\woo\d*/';
    preg_match($pattern,$subject,$matches,PREG_OFFSET_CAPTURE); 
    print_r($matches);
?>

輸出結果:
在這裡插入圖片描述
3.定義斷言限定符

\b:單詞定界符
\B:非單詞定界符
\A:字串開頭,類似^,但不受處理多行選項的影響
\Z:字串結尾或行尾(換行符之前的位置),但不受處理多行選項的影響
\z:字串結尾,類似$
\G:當前搜尋的開頭

11.小括號

1.改變作用範圍
【例1】
顯示了小括號在改變選擇符和限定符的作用範圍

<?php
    $subject = "html-HTml-goo123oogle";
    $pattern = '/(ht|HT)ml/';
    preg_match($pattern,$subject,$matches,PREG_OFFSET_CAPTURE); 
    print_r($matches);
?>

輸出結果:
在這裡插入圖片描述

$pattern = '/(ht)ml|(HT)ml/';

輸出結果:
在這裡插入圖片描述

$pattern = '/(goo){1,3}/';

輸出結果:
在這裡插入圖片描述
2.定義子表示式
子表示式相當於一個獨立的正則表示式。子表示式具有記憶功能,能夠臨時儲存其匹配的字元,然後可以在後面進行引用。

12.修飾符

主要調整正則表示式的解釋,增強了正則表示式的能力。

i:不區分大小寫
m:將字串視為多行
s:將字串視為一行
x:忽略空白(進行轉義的空白不被忽略)
A:匹配字串開頭部分
D:模式中的$僅匹配字串的結尾

x02 使用PCRE擴充套件正則表示式函式

正則表示式需要在相應的正則表達函式應用,才能實現對字串的匹配、查詢、替換及分割操作。在PHP中有兩套正則表示式的函式庫。主要講解以”preg_“開頭的PCRE擴充套件函式。

1.陣列過濾

preg_grep()函式能夠使用正則表示式過濾陣列中的元素。

array preg_grep(string $pattern,array $input[,int $flags = 0]]) //匹配查詢,返回一個數組;
pattern:要搜素的正則模式
input:輸入陣列
flags:若設定為PREG_GREP_INVERT,將返回輸入陣列中與給定模式pattern不匹配的元素組成的陣列
preg_grep()函式將返回給定陣列input中與模式pattern相匹配的元素組成的陣列。返回陣列將使用input引數陣列中key做索引。
<?php
    $array = array(2,3,45,"a",4.5,9.8,.9);
    $pattern = '/^(\d*)?\.\d+$/';
    $final = preg_grep($pattern,$array); 
    print_r($final);
?>

輸出結果:
在這裡插入圖片描述

2.執行一次匹配

preg_match()函式能偶執行一個正則表示式匹配。

int preg_match(string $pattern,string $subject [,array &$matches [,int $flags = 0 [,int $offset = 0]]])
pattern:要搜尋的正則模式
subject:輸入字串
matches:如果提供了該引數,它將填充為搜素結果。$matches[0]包含完整匹配到的文字,$matches[1]將包含第一個捕獲子組匹配到的文字,以此類推。
flags:可設定為PREG_OFFSET_CAPTURE,表示對於每一個匹配返回時,附加字串偏移量
offset:用於從目標字串的某個位置開始搜尋,單位是位元組
preg_match()函式將返回pattern得匹配次數。返回值是0(不匹配)或1次,preg_match()在第一次匹配後將會停止搜尋。

【例1】快速檢測給定字串中是否包含”php“,匹配字元不區分大小寫

<?php
    $subject = "PHP is a nb language.PHP is nice";
    $pattern = '/php/i';
    echo preg_match($pattern,$subject);   //輸出 1
?>

【例2】從URL字串中匹配出域名子串

<?php
    $subject = "http://www.baidu.com/index.html";
    $pattern = '/^(http:\/\/)?([^\/]+)/i';  
    preg_match($pattern,$subject,$matches);
    echo "$matches[0]\n"."~~"; 
    echo "$matches[1]\n"."~~";  
    echo "$matches[2]\n"."~~";  

    $subject = $matches[2];
   $pattern = '/[^.]+\.[^.]+$/';
   preg_match($pattern,$subject,$matches);
   echo "域名:$matches[0]\n";
?>

輸出結果:
在這裡插入圖片描述

注意:如果只是想要檢查一個字串是否包含另外一個字串,建議使用strpos()或strstr()函式。

3.執行所有匹配

preg_match_all()函式能夠執行一個全域性正則表示式匹配。

int preg_match_all(string $pattern,string $subject [,array &$matches [,int $flags = PREG_PATTERN_ORDER [,int $offset = 0]]])
pattern:要搜尋的正則模式
subject:輸入字串
matches:多維陣列,作輸出引數,輸出所有匹配結果。陣列排序通過flags指定
flags:若不指定排序標記,預設為PREG_PATTERN_ORDER
PREG_PATTERN_ORDER:結果排序為$matches[0]儲存完整模式的所有匹配,$matches[1]儲存第一個子組的所有匹配,以此類推
PREG_SET_ORDER:結果排序為$matches[0]包含第一次匹配得到的所有匹配(包含子組),$matches[1]包含第二次匹配的所有匹配(包含子組)的陣列,以此類推
PREG_OFFSET_CAPTURE:每個發現的匹配返回時會增加它相對目標字串的偏移量
offset:用於從目標字串的某個位置開始搜尋,單位是位元組

preg_match_all()函式能夠搜尋subject中所有匹配pattern給地那個正則表示式的匹配結果,並且以flags指定順序輸出到matches中。第一次匹配找到後,子序列繼續從最後一次匹配位置搜尋。
【例1】找出HTML字串所有標籤,及其包含的文字等資訊

<?php
    $html = "<b>加粗文字</b><p>段落文字</p>";
    $pattern = '/(<([\w]+)>)(.*)(<\/.*\2>)/';
    preg_match_all($pattern,$html,$matches,PREG_SET_ORDER);

    foreach($matches as $val){
        echo "匹配資訊:"."$val[0]"."\n";
        echo "子組1:"."$val[1]"."\n";
        echo "子組2:"."$val[2]"."\n";
        echo "子組3:"."$val[3]"."\n";
        echo "子組4:"."$val[4]"."\n";
    }
?>

輸出結果:(忽略以下的雙引號)
在這裡插入圖片描述

4.轉義字元

preg_quote()函式能夠轉義正則表示式字元。

string preg_quote(string $str[,string $delimiter = NULL])
str:輸入字串
delimiter:指定會被轉義的字元

preg_quote()函式在str中每個正則表示式語法中的特殊字元前新增一個反斜槓""
【例1】對字串中的特殊字元進行轉義

<?php
    $str = '2020/12/31 0.59$';
    $str = preg_quote($str,NULL);
    echo $str;    
?>

輸出結果:
在這裡插入圖片描述

$str = preg_quote($str,'/');

輸出結果:
在這裡插入圖片描述

5.查詢替換

preg_replace()函式能夠執行一個正則表示式的搜尋和替換。

mixed preg_replace(mixed $pattern,mixed $replacement,mixed $subject[,int $limit = -1[,int &$count]])
pattern:要搜尋的正則模式
replacement:用於替換的字串和字串陣列
subject:要進行搜尋和替換的字串和字串陣列
limit:每個模式在每個subject上進行替換的最大次數
count:若指定該引數,將會被填充為完成的替換次數

如果subject是陣列,preg_replace()返回一個數組,其他情況返回一個字串。如果匹配被找到,替換後的subject被返回,反之則返回原subject
【例1】使用反向引用修改字串中的數字和顯示格式

<?php
    $subject = 'DEC-31,2020';
    $pattern = '/(\w+)-(\d+),(\d+)/i';
    $replacement = '$3-$1-31';
    echo preg_replace($pattern,$replacement,$subject);
?>

輸出結果:
在這裡插入圖片描述
反向引用這裡看圖理解即可
在這裡插入圖片描述

6.分隔字串

preg_split()函式能夠通過一個正則表示式分隔字串。

array preg_split(string $pattern,string $subject[,int $limit = -1[,int flags = 0]])
pattern:要搜尋的正則模式
subject:輸入字串
limit:若指定,將限制分隔得到的字串最多隻有limit個。limit值為-10NULL代表不限制
flags:
PREG_SPLIT_NO_EMPTY:返回分隔後的非空部分
PREG_SPLIT_DELIM_CAPTURE:分隔模式中的括號表示式將被捕獲並返回
PREG_SPLIT_OFFSET_CAPTURE:匹配返回時附加字串偏移量

preg_split()函式將返回一個使用pattern邊界分隔subject後得到的子串組成的陣列
【例1】將一個短語分隔為多個單詞

<?php
    $subject = 'Hi,,,how are you';
    $pattern = '/[\s,]+/';
    $matches = preg_split($pattern,$subject,PREG_SPLIT_OFFSET_CAPTURE);
    print_r($matches);
?>

輸出結果:
在這裡插入圖片描述

GOT IT!持續更新~


******************************************************
具體利用方式需根據具體實踐場景~