## 正則表達式
正則表達式(regular expression)描述了一種字符串匹配的模式(pattern),可以用來檢查一個串是否含有某種子串、將匹配的子串替換或者從某個串中取出符合某個條件的子串等。
正則表達式是由 **普通字符**(例如字符 a 到 z)以及 **元字符** 組成的文字模式。正則表達式作為一個模板,將某個字符模式與所搜索的字符串進行匹配。
### 分隔符
當使用 PCRE 函數的時候,模式需要由分隔符閉合包裹。分隔符可以使任意非字母數字、非反斜線、非空白字符。
經常使用的分隔符是正斜線(/)、hash符號(#) 以及取反符號(~)下面的例子都是使用合法分隔符的模式。
- /foo bar/
- \#^[^0-9]$\#
- +php+
- %[a-zA-Z0-9_-]%
### 元字符
正則表達式的威力源于它可以在模式中擁有選擇和重復的能力。 一些字符被賦予特殊的涵義,使其不再單純的代表自己,模式中的這種有特殊涵義的編碼字符稱為元字符。
共有兩種不同的元字符: 一種是可以在方括號外任何地方使用的,一種是需要在方括號內使用的。
**方括號外使用的元字符:**
| 字符 | 描述 |
| --- | --- |
| \ | 轉義字符 |
| ^ | 斷言目標的開始位置(或在多行模式下是行首) |
| $ | 斷言目標的結束位置(或在多行模式下是行尾) |
| . | 匹配除換行符外的任何字符(默認) |
| [ | 開始字符類定義 |
| ] | 結束字符類定義 |
| \| | 開始一個可選分支 |
| ( | 子組的開始標記 |
| ) | 子組的結束標記 |
| ? | 作為量詞,表示 0 次或 1 次匹配。位于量詞后面用于改變量詞的貪婪特性 |
| * | 量詞,0 次或多次匹配 |
| + | 量詞,1 次或多次匹配 |
| { | 自定義量詞開始標記 |
| } | 自定義量詞結束標記 |
**方括號內使用的元字符:**
| 字符 | 描述 |
| --- | --- |
| \ | 轉義字符 |
| ^ | 僅在作為第一個字符時,表明字符類取反 |
| - | 標記字符范圍 |
**限定符(量詞)**
限定符主要是用來限定每個字符串出現的次數。
| 限定字符 | 含義 |
| --- | --- |
| ? | 零次或一次,等價于 {0,1} |
| * | 零次或多次, 等價于 {0,n}|
| + | 一次或多次, 等價于 {1,n} |
| {n} | n 次 |
| {n,} | 至少 n 次 |
| {n,m} | n 到 m 次 |
### 轉義序列(反斜線)
表達式中的反斜杠有多重意義,如轉義字符、顯示非打印的字符、指定預定義的字符集、定義斷言。
** (1)轉義字符 **
轉義字符主要是將一些特殊字符轉為普通字符。比如要匹配元字符,就需要在他們前面加上反斜線,例如:\?, \^, \$
** (2)顯示非打印字符 **
非打印字符也可以是正則表達式的組成部分,常見的非打印字符轉義序列:
| 字符 | 含義 |
| --- | --- |
| \b | 退格 |
| \f | 換頁符 |
| \n | 換行符 |
| \r | 回車符 |
| \s | 任何空白字符,包括空格、制表符、換頁符等 |
| \S | 任何非空白字符 |
| \t | 制表符 |
| \v | 垂直制表符 |
**后向引用**
后向引用依靠子表達式的 ”記憶” 功能,匹配連續出現的字串或是字符。如:(abc)(123)\1\2,表示匹配字符串 abc123abc123
** (3)指定預定義的字符集 **
| 字符 | 含義 |
| --- | --- |
| \d | 任意十進制數字 |
| \D | 任意非十進制數字 |
| \s | 任意空白字符 |
|\S | 任意非空白字符 |
| \w | 任意單詞字符(數字,字母,下劃線)|
| \W | 任意非單詞字符 |
** (4)定義斷言 **
一個斷言指定一個必須在特定位置匹配的條件, 它們不會從目標字符串中消耗任何字符。
| 字符 | 含義 |
| --- | --- |
| \b | 單詞邊界 |
| \B | 非單詞邊界 |
| \A | 目標的開始位置(獨立于多行模式)|
| \z | 目標的結束位置(獨立于多行模式)|
| \Z | 目標的結束位置或結束處的換行符(獨立于多行模式)|
| \G | 在目標中首次匹配位置 |
### 模式修飾符
模式修飾符的作用是設定模式,也就是正則表達式如何解釋。php 中主要模式如下:
| 修飾符 | 說明 |
| --- | --- |
| i | 忽略大小寫 |
| m | 多行文本模式 |
| s | 單行文本模式 |
| x | 忽略空白字符 |
### 表達式示例
匹配特殊字符,例如:$foo, [abc], c++
/\$foo/
/\[abc\]/
/c\+\+/
匹配以 face 開頭的字符串,例如:facebook
/^face/
匹配以 book 結尾的字符串,例如:facebook
/book$/
表達式將匹配 facebook, gitbook
/(face|git)book/
匹配包含元音的字符串
/[aeiou]/
匹配英文字母和阿拉伯數字
/[a-zA-Z0-9]/
匹配非阿拉伯數字
/[^0-9]/
表達式將匹配 gogle, google, gooogle, goo...ogle
/goo*gle/
/goo{0,}gle/
表達式將匹配 gogle, google
/goo?gle/
/goo{0,1}gle/
表達式將匹配 google,gooogle, goo...ogle
/goo+gle/
/goo{1,}gle/
表達式將匹配 google, gooogle, goooogle
/goo{1,3}gle/
表達式將匹配 gooogle
/goo{2}gle/
表達式將匹配 2017-05-21, 0000-00-00, 1234-56-78
/\d{4}-\d{2}-\d{2}/
匹配一個完整的單詞,例如: tom and jerry
/\band\b/
匹配忽略大小寫,表達式將匹配 google, Google, GOOGLE
/google/i
### 貪婪匹配與惰性匹配
- 貪婪匹配:就是匹配盡可能多的字符。
- 懶惰匹配:就是匹配盡可能少的字符。
例如使用表達式 `/<div>.*<\/div>/` 匹配字符串 `<div>google</div><div>facebook</div>`
- 貪婪匹配返回: `<div>google</div><div>facebook</div>`
- 懶惰匹配返回: `<div>google</div>`
**注意:** 默認情況下,量詞都是 ”貪婪” 的,在量詞后面加上?(問號)標記,它就會轉換成懶惰匹配。
### PRCE 函數
```
<?php
$html = <<<EOT
{div class="list"}php{/div}
{div class="list"}python{/div}
{div class="list"}java{/div}
EOT;
$pattern = '/{div class="list"}(.*?){\/div}/';
preg_match($pattern, $html, $matches);
print_r($matches);
preg_match_all($pattern, $html, $matches);
print_r($matches);
$str = '小明的出生日期: 1997-10-01';
$pattern = '/(\d{4})-(\d{2})-(\d{2})/i';
$output = preg_replace($pattern, '$1 年 $2 月 $3 日', $str);
echo $output . PHP_EOL;
$output = preg_replace_callback($pattern, function($matches){
return "{$matches[1]} 年 {$matches[2]} 月 {$matches[3]} 日";
}, $str);
echo $output . PHP_EOL;
?>
```
參考鏈接:
- [模式語法](http://php.net/manual/zh/reference.pcre.pattern.syntax.php)
- [模式修飾符](http://php.net/manual/zh/reference.pcre.pattern.modifiers.php)
- [PCRE函數](http://php.net/manual/zh/ref.pcre.php)
- 基本語法
- PHP標記
- 指令分隔符
- 從HTML中分離
- 注釋
- 數據類型
- 布爾值
- 整數
- 浮點數
- 字符串
- 數組
- 對象
- 資源
- 空值
- 變量
- 基礎
- 預定義變量
- 變量范圍
- 可變變量
- 常量
- 常量語法
- 魔術常量
- 運算符
- 算術運算符
- 賦值運算符
- 位運算符
- 比較運算符
- 遞增與遞減運算符
- 邏輯運算符
- 字符串運算符
- 數組運算符
- 類型運算符
- 流程控制
- if條件結構
- switch條件結構
- while循環結構
- do-while循環結構
- for循環結構
- foreach循環結構
- 包含文件
- 函數
- 自定義函數
- 可變函數
- 匿名函數
- 遞歸函數
- 類與對象
- 基本概念
- 屬性
- 方法
- 類常量
- 構造函數和析構函數
- 訪問控制
- 繼承
- 抽象類
- 接口
- Trait
- 重載
- 對象遍歷
- 魔術方法
- Final關鍵字
- 命名空間
- 自動加載
- 錯誤處理
- 錯誤顯示
- 錯誤日志
- 錯誤報告
- 自定義錯誤處理
- 異常處理
- 異常處理機制
- 擴展異常處理類
- 字符操作
- 數組操作
- 時間操作
- 表單操作
- GET提交
- POST提交
- 文件上傳
- 會話控制
- COOKIE操作
- SESSION操作
- 文件操作
- 文件屬性
- 讀取文件
- 寫入文件
- 文件管理
- 文件鎖
- 目錄處理
- 路徑處理
- 網絡操作
- HTTP協議
- Socket操作
- CURL操作
- PDO操作
- 介紹
- 連接管理
- 預處理語句
- 事務處理
- 錯誤處理
- 圖像操作
- 正則表達式
- 標準推薦
- 包管理器
- 設計模式
- 常用算法
- 安全防御
- XSS防御
- CSRF防御