PHP 正則表達式筆記

来源:http://www.cnblogs.com/avilang/archive/2016/01/14/5130625.html
-Advertisement-
Play Games

什麼是正則表達式在電腦上我們經常會使用(通配符)找出我們需要的文件,例如:*.doc ,這裡的 * 代表匹配零個或多個字元。正則表達式也是用來進行文本匹配的工具,只不過它更加強悍。引用 PHP 手冊里的一句話:正則表達式是一個從左到右匹配目標字元串的模式,大多數字元自身就代表一個匹配 它們自身的模式...


什麼是正則表達式

在電腦上我們經常會使用(通配符)找出我們需要的文件,例如:*.doc ,這裡的 * 代表匹配零個或多個字元。正則表達式也是用來進行文本匹配的工具,只不過它更加強悍。引用 PHP 手冊里的一句話:正則表達式是一個從左到右匹配目標字元串的模式,大多數字元自身就代表一個匹配 它們自身的模式。

下麵給出幾個簡單例子,使對正則表達式有個初步的理解。

hi  //匹配英文字元(忽略大小寫) hi , HI , Hi , hI
\bhi\b  //匹配英文單詞 hi  '\b'是正則里的一特殊字元(一種斷言),表示單詞邊界
\bhi\b.*\bLucy\b  //匹配如:'hi my name is Lucy'  '.' 表示匹配除換行符以外的任意字元  '*' 是量詞,表示重覆零次或更多次
0\d{2}-\d{8}  //匹配如: 020-12345678  '\d' 匹配一個數字(0-9)    '{n}' 重覆n次,如{2} {8}

上面例子中的 \b , . , * , \d , {2} 都有特殊含義,在下文會有說明。

PHP 中正則語法

1.簡介

在 PHP 里支持兩種正則分別是 POSIX 和 PCRE 。自 PHP 5.3.0起,POSIX 正則表達式擴展被廢棄。所以下文討論的都是基於 PCRE 模式。可點擊查看有關與 POSIX 正則表達式的不同與 perl 的不同之處

2.分隔符

當使用 PCRE 函數 的時候,模式需要由分隔符閉合包裹。分隔符可以使任意非字母數字、非反斜線、非空白字元。經常使用的分隔符是正斜線 / 、hash符號 # 以及取反符號 ~ 。下麵的例子都是使用合法分隔符的模式。

/foo bar/
#^[^0-9]$#
+php+
%[a-zA-Z0-9_-]%

如果分隔符需要在模式內進行匹配,它必須使用反斜線進行轉義。如果分隔符經常在模式內出現,一個更好的選擇就是是用其他分隔符來提高可讀性。例:

/http:\/\//
#http://#

3.元字元

正則表達式的威力源於它可以在模式中擁有選擇和重覆的能力。一些字元被賦予特殊的含義,使其不再單純的代表自己,模式中的這種有特殊涵義的編碼字元 稱為元字元
共有兩種不同的元字元:一種是可以在模式中方括弧外任何地方使用的,另外一種是需要在方括弧內使用的。

在方括弧外使用的元字元如下:

代碼說明
/ 一般用於轉義字元
^ 斷言目標的開始位置(或在多行模式下是行首)
$ 斷言目標的結束位置(或在多行模式下是行尾)
. 匹配除換行符外的任何字元(預設)
[ 開始字元類定義
] 結束字元類定義
| 開始一個可選分支
( 子組的開始標記
) 子組的結束標記
? a:作為量詞,表示 0 次或 1 次匹配。b:位於量詞後面用於改變數詞的貪婪特性。
* 量詞,0 次或多次匹配
+ 量詞,1 次或多次匹配
{ 自定義量詞開始標記
} 自定義量詞結束標記

模式中方括弧內的部分稱為“字元類”。 在一個字元類中僅有以下可用元字元:

代碼說明
\ 轉義字元
^ 僅在作為第一個字元(方括弧內)時,表明字元類取反
- 標記字元範圍

示例:

  • \ba\w*\b 匹配以字母 a 開頭的單詞,先是某個單詞開始處 \b ,然後是字母 a ,然後是任意數量的任意單詞字元(單詞字元指的是任意字母、數字、下劃線) \w* ,最後是單詞結束處 \b 。
  • \d+ 匹配1個或更多連續的數字。
  • ^\d{5,12}$ 匹配為5位到12位數字,因為使用了 ^ 和 $ ,所以輸入的整個字元串都要用來和 \d{5,12} 來匹配,也就是說整個輸入必須是5到12個數字。

4.轉義序列(反斜線)

反斜線 \ 有四種用法,詳細可點擊 轉義序列(反斜線)

【1】作為轉義字元,比如,如果你希望匹配一個 * 字元,就需要在模式中寫為 \* 。這適用於一個字元在不進行轉義會有特殊含義的情況下。 但是,對於非數字字母的字元,總是在需要其進行原文匹配的時候在它前面增加一個反斜線,來聲明它代表自己,這是安全的。如果要匹配一個反斜線,那麼在模式中使用 \\
反斜線在單引號字元串和雙引號字元串中都有特殊含義,因此要匹配一個反斜線, 模式中必須寫為 \\\\ 。其中的原因:首先它作為字元串,反斜線會進行轉義。最後正則表達式引擎也認為反斜線是轉義。因此,需要 4 個反斜線才可以匹配一個反斜線。

【2】提供了一種對非列印字元進行可見編碼的控制手段

【3】用來描述特定的字元類

代碼說明
\d 任意十進位數字
\D 任意非十進位數字
\h 任意水平空白字元(since PHP 5.2.4)
\H 任意非水平空白字元(since PHP 5.2.4)
\s 任意空白字元
\S 任意非空白字元
\v 任意垂直空白字元(since PHP 5.2.4)
\V 任意非垂直空白字元(since PHP 5.2.4)
\w 任意單詞字元,單詞字元指的是任意字母、數字、下劃線。
\W 任意非單詞字元

【4】一些簡單的斷言。一個斷言指定一個必須在特定位置匹配的條件,它們不會從目標字元串中消耗任何字元。反斜線斷言包括:

  • \b 單詞邊界
  • \B 非單詞邊界
  • \A 目標的開始位置(獨立於多行模式)
  • \Z 目標的結束位置或結束處的換行符(獨立於多行模式)
  • \z 目標的結束位置(獨立於多行模式)
  • \G 在目標中首次匹配位置

5.重覆/量詞

代碼說明
* 重覆零次或更多次,等價於
+ 重覆一次或更多次,等價於
? 重覆零次或一次,等價於
{n} 重覆n次
{n,} 重覆n次或更多次
{n,m} 重覆n到m次

預設情況下,量詞都是”貪婪”的,也就是說,它們會在不導致模式匹配失敗的前提下,儘可能多的匹配字元(直到最大允許的匹配次數)。然而,如果一個量詞緊跟著一個 ? 標記,它就會成為懶惰(非貪婪)模式, 它不再儘可能多的匹配,而是儘可能少的匹配。
下麵直接看示例,理解“貪婪”和“非貪婪”模式是怎麼回事。

對於字元串 "aa<div>test1</div>bb<div>test2</div>cc"

正則表達式 "<div>.*</div>"    匹配結果 "<div>test1</div>bb<div>test2</div>"

正則表達式 "<div>.*?</div>"   匹配結果 "<div>test1</div>"

關於更多“貪婪”和“非貪婪”模式的介紹可查閱 http://php.net/manual/zh/regexp.reference.repetition.php

6.字元類(方括弧)

PHP手冊中的描述:

  • 左方括弧開始一個字元類的描述,並以方中括弧結束。單獨的一個右方括弧沒有特殊含義。如果一個右方括弧需要作為一個字元類中的成員,那麼可以將它寫在字元類的首字元處(如果使用了 ^ 取反,那麼是第二個)或者使用轉義符。

  • 一個字元類在目標字元串中匹配一個單獨的字元;該字元必須是字元類中定義的字元集合的其中一個, 除非使用了 ^ 對字元類取反。如果^需要作為一個字元類的成員,確保它不是該字元類的首字元,或者對其進行轉義即可。

示例:

[aeiou]    //匹配所有的小寫母音字母

[^aeiou]   //匹配所有非母音字母的字元

[.?!]      //匹配標點符號(.或?或!)

註意:^ 只是一個通過枚舉指定那些不存在字元類之中的字元的便利符號。而不是斷言, 它仍然會從目標字元串中消耗一個字元,並且如果當前匹配點在目標字元串末尾, 匹配將會失敗。

輕鬆地指定一個字元範圍,範圍操作以 ASCII 整理排序。它們可以用於為字元指定數值,比如 [\000-\037]

[0-9]    //代表的含意與 '\d' 就是完全一致的
[a-z0-9A-Z_]    //完全等同於 '\w' 如果只考慮英文的話

下麵是一個更複雜的表達式 \(?0\d{2}[) -]?\d{8}
這個表達式可以匹配幾種格式的電話號碼,像 (010)88886666,或 022-22334455 ,或 02912345678 等。
簡單分析:首先是一個轉義字元 \( ,它能出現 0 次或 1 次 ? ,然後是一個數字 0 ,後面跟著 2 個數字 \d{2} ,然後是 )- 或 “空格” 中的一個,它出現 0 次或 1 次,最後是 8 個數字 \d{8}

7.分支 ( | )

豎線字元用於分離模式中的可選路徑。比如模式 gilbert|Sullivan 匹配 ”gilbert” 或者 ”sullivan”。豎線可以在模式中出現任意多個,並且允許有空的可選路徑(匹配空字元串)。匹配的處理從左到右嘗試每一個可選路徑,並且使用第一個成功匹配的。如果可選路徑在子組(下麵定義)中,則”成功匹配”表示同時匹配了子模式中的分支以及主模式中的其他部分。

回看上文里的一個例子 \(?0\d{2}[) -]?\d{8} 這個正則也能匹配 010)12345678 或 (022-87654321 這樣的 “不正確” 的格式。其實我們可以利用分支就能解決這個問題,如下:

\({1}0\d{2}\){1}[- ]?\d{8}|0\d{2}[- ]?\d{8} 這個表達式匹配 3 位區號的電話號碼,其中區號可以用小括弧括起來,也可以不用,區號與本地號間可以用連字型大小或空格間隔,也可以沒有間隔。

使用分枝條件時,要註意各個條件的順序

8.內部選項設置

正則表達式在不同的模式修飾符下匹配出的結果有可能不相同。它的語法是 :(?修飾符)

比如,(?im) 設置表明多行大小寫不敏感匹配。同樣可以用它來取消這些設置,比如 (?im-sx) 設置了 “PCRE_CASELESS”,”PCRE_MULTILINE”,但是同時取消了 “PCRE_DOTALL” 和 “PCRE_EXTENDED”。如果一個字母即出現在 - 之前, 也出現在 - 之後,這個選項被取消設置。

下麵緊例舉簡單的示例,想要瞭解更多可點擊 內部選項設置模式修飾符

示例:/ab(?i)c/ 僅僅匹配 ”abc” 和 ”abC”

9.子組(子模式)

子組通過圓括弧分隔界定,並且它們可以嵌套。

示例:

字元串:"the red king"
正則表達式:((red|white) (king|queen))
匹配結果:array("red king", "red king", "red", "king")
描述:其中第 0 個元素是整個模式匹配的結果,後面的三個元素依次為三個子組匹配的結果。 它們的下標分別為 1, 2, 3。

經常我們會有一種需求需要使用子組進行分組,但又不需要(單獨的)捕獲它們。在子組定義的左括弧後面緊跟字元串 ?: 會使得該子組不被單獨捕獲,並且不會對其後子組序號的計算產生影響。例如:

字元串:"the red king"
正則表達式:((?:red|white) (king|queen))
匹配結果:array("red king", "red king", "king")

為了方便簡寫,如果需要在非捕獲子組開始位置設置選項, 選項字母可以位於 ?: 之間,比如:

(?i:saturday|sunday)
(?:(?i)saturday|sunday)

上面兩種寫法實際上是相同的模式。因為可選分支會從左到右嘗試每個分支,並且選項沒有在子模式結束前被重置,並且由於選項的設置會穿透對後面的其他分支產生影響,因此, 上面的模式都會匹配 ”SUNDAY” 以及 ”Saturday”。

再看一個匹配 IP 地址的正則 ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)
相關文章 IP地址的正則表達式

結語

上文中涉及 PHP 正則表達式中常用的語法,有的語法沒細說和涉及到的,如:模式修飾符、後向引用、斷言、遞歸模式,等。你可以通過 PHP 手冊查看這些內容。

提示:一般而言,對於同樣的功能,正則表達式函數運行效率要低於字元串函數。如果應用程式較簡單,那麼就用字元串表達式。但是,對於可以通過單個正則表達式執行的任務來說,如果使用多個字元串函數,則是不對的。 ---- 摘自《PHP 和 MySQL Web 開放》一書。

參考資料

http://php.net/manual/zh/book.pcre.php
https://msdn.microsoft.com/zh-cn/library/d9eze55x%28v=vs.80%29.aspx
http://deerchao.net/tutorials/regex/regex.htm
http://tool.chinaz.com/regex/
http://www.regexlab.com/zh/regref.htm


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在Linux系統中,我們查看、監控系統記憶體使用情況,一般最常用的命令就是free。free命令其實非常簡單,參數也非常簡單,但是裡面很多知識點未必你都掌握了。下麵總結一下我所瞭解的free命令。如有不足,敬請指出。文章很多知識點參考了下麵參考資料,都是在這些前輩文章的基礎上所做的一個驗證和總結。 f...
  • 切換分支出現如下提示,並且自動簽出了項目文件csproj。 修改項目文件csproj 修改前: true 修改後: true 44301 enabled disabled false
  • using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windows;using System.Windows.Controls;using System.Wind...
  • 今天用HTTP.HttpClient這個對象開發的時候遇到一個奇怪的問題 當POST一個頁面的時候始終卡住提交不成功最初以為協議有錯誤就抓包測試在抓包在測試 最後想到是不是HttpClient的BUG?當使用另一種語言提交同樣的包就沒問題後來抓包對比這2個語言發出的包發現HttpClient預設是開...
  • 首先,推薦兩個關於python爬蟲不錯的博客:Python爬蟲入門教程專欄 和 Python爬蟲學習系列教程。寫的都非常不錯,我學習到了很多東西!在此,我就我看到的學到的進行總結一下! 爬蟲就是一個不斷的去抓去網頁的程式,根據我們的需要得到我們想要的結果!但我們又要讓伺服器感覺是我們人在通過瀏...
  • 依賴註入依賴註入支持屬性註入、構造函數註入、工廠註入。屬性註入:屬性註入即通過setXxx()方法註入Bean的屬性值或依賴對象屬性註入要求Bean提供一個預設的構造函數(無參構造函數),併為需要註入的屬性提供對應的Setter方法過程:Spring先調用Bean的預設構造函數實例化Bean對象,然...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...