程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> Php中正則小結(一)

Php中正則小結(一)

編輯:關於PHP編程

一.概念

語法模式類似.

分隔符可以是任意非字母非數字,除反斜槓

 

 

如果分隔符 在表達式中使用,需要使用反斜線進行轉義

 

元字符

一個正則表達式基本組成

 

/原子和元字符/模式修正符              /代表定界符的一個

正則表達式的威力在於其能夠在模式中包含選擇和循環。它們通過使用元字符來編碼在模式中,元字符不代表其自身,它們用一些特殊的方式來解析。

根據在方括號的內部還是外部分為兩種。

 1.方括號之外的元字符

元字符(符號)

說明

\

一般用於轉義字符

^

斷言目標的開始位置(或在多行模式下是行首)

$

目標的結束位置(活在多行模式下行尾)

.

匹配除換行符外任何字符(默認時)

[,]

開始,結束字符類定義

|

開始一個可選分支

( ,)

子組的開始,結尾標記

?

作為量詞,表示 0 次或 1 次匹配。位於量詞後面用於改變量詞的貪婪特性

*

量詞,0 次或多次匹配

 

+

量詞,1 次或多次匹配

 

{ ,}

自定義量詞開始標記,結束標記

 

 

2.模式中方括號內的部分稱為“字符類”

元字符

說明

\

轉義字符

^

僅在作為第一個字符時,表明字符類取反

-

標記字符范圍

元字符用法說明舉例

1.轉義(反斜線)

\後緊跟著一個非字母數字字符,則取消該字符可能具有的任何特殊含義。此種適用於字符類之中或之外。

對於非數字字母的字符,總是需要其進行原文匹配時候在它前面加一個反斜線,來代表它代表自己。

 

匹配 “*” 時,由於其有特殊含義,所以用 “\*”取消掉了其特殊含義

匹配”.”用”\.”

匹配”\” 用”\\”

但要注意:

反斜線在單引號字符串和雙引號字符串中都有特殊含義,因此要匹配一個反斜線,模式中必須寫”\\\\”或’\\\’

 

2.反斜線第二種用途提供了一種對非打印字符進行可見編碼的控制手段。除了二進制的

 

符號

說明

\a

 

響鈴字符(十六進制 07)

 

\cx

"control-x",x 是任意字符

 

\e

轉義 (十六進制 1B)

 

\f

換頁 (十六進制 0C)

 

\n

換行 (十六進制 0A)

 

\p{xx} (p

一個符合 xx 屬性的字符

\P{xx} (p

一個不符合 xx 屬性的字符

\r

回車 (十六進制 0D)

 

\t

水平制表符 (十六進制 09)

 

\xhh

  hh十六進制編碼的字符

\ddd

ddd八進制編碼的字符,或者後向引用

 

\040

空格的另外一種用法

 

\40

當提供了少於40個子組時也認為是空格。 

 

\7

始終是後向引用

 

\11

可能是後向引用,也可能是制表符

\011

總是一個制表符

 

\0113

一個制表符緊跟著一個3(因為每次最多只讀取3個8進制位

 

\113

八進制113代表的字符 

 

\377

8進制377是10進制255, 因此代表一個全1的字符

 

\81

一個後向引用或者一個二進制 0 緊跟著兩個數字 8 和 1(因為8不是8進制有效數字) 

 

3.反斜線第三種用法,描述特定的字符類

符號

說明

\d

任意十進制數字

\D

任意非十進制數字

\h

任意水平空白字符

\H

任意非水平空白字符

\s

任意空白字符

\S

任意空白字符

\v

任意垂直空白字符(since PHP 5.2.4)

 

\V

任意非垂直空白字符(since PHP 5.2.4)

 

\w

任意單詞字符

 

\W

任意非單詞字符

 

上面每一對轉義序列都代表了完整字符集中兩個不相交的部分, 任意字符一定會匹配其中一個,同時一定不會匹配另外一個。

 

第四種用法 簡單的斷言

\b

單詞邊界 注意在字符類中是退格

 

\B

非單詞邊界

 

\A

目標的開始位置(獨立於多行模式)

 

\Z

目標的結束位置或結束處的換行符(獨立於多行模式) 

 

\z

目標的結束位置(獨立於多行模式)

 

\G

在目標中首次匹配位置

 

\A,\Z,\z

 

因為他們永遠匹配目標字符串的開始和結尾,而不會受模式修飾符的限制

 

\Z和 \z之間的不同在於當字符串結束字符時換行符時 \Z 會將其看做字符串結尾匹配, 而 \z 只匹配字符串結尾。

 

代碼1

='#\A[a-z]{3}#m'=''(,,();

發現後面加不加模式修正符m

只匹配到

而代碼

 

='#^[a-z]{3}#m'=''(,,();

 

不加m

加上之後匹配了

果真,

同理可比較

 

代碼

 

='#[a-z]\Z#'="a\n"(,,();

模式修正為\E

當模式修正為

 

 

在指定了$offset 參數的 preg_match()() 調用中, 僅在當前匹配位置在匹配開始點的時候才是成功的

 

 當 $offset 的值不為 0 的時候, 它與 \A 是不同的。

 

參見php手冊

 

 

即把有特殊含義的字符放在\Q與\E之間

 

如代碼4

='#\w+\Q.$.\E$#'="a.$."(,,();

匹配到 a.$.

 

自 PHP 5.2.4 開始。。 比如, foot\Kbar 匹配”footbar”。 但是得到的匹配結果是 ”bar”。但是, \K 的使用不會干預到子組內的內容, 比如 (foot)\Kbar 匹配 ”footbar”,第一個子組內的結果仍然會是 ”foo”。譯注: \K 放在子組和子組外面的效果是一樣的。

\p{Lu}匹配大寫字母

句點

在字符類外部

\C可以被用於匹配單字節, 也就是說在UTF-8模式下,句點可以匹配多字節字符

Character classes

alnum

字母和數字

alpha

字母

ascii

0 - 127的ascii字符

blank

空格和水平制表符

cntrl

控制字符

digit

十進制數(same as \d)

graph

打印字符, 不包括空格

lower

小寫字母

print

打印字符,包含空格

punct

打印字符, 不包括字母和數字

space

空白字符 (比\s多垂直制表符)

upper

大寫字母

word

單詞字符(same as \w)

xdigit

十六進制數字

 

 

 

 

比如'#[[:upper:]]#'匹配大寫字母

'#[[:alpha:]]#'   匹配字母

 

 

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

代碼5

='#p(hp|ython|erl)#'="php python perl"(,,();

子組通過圓括號分割界定,並且它們可以嵌套,主要有以下兩種用法與功能

1.將可選分支局部化。比如

模式 p(hp|ython|erl) 匹配

2.將子組設定為捕獲子組

整個模式匹配後, 左括號從左至右出現的次序就是對應子組的下標(從 1 開始), 可以通過這些下標數字來獲取捕獲子模式匹配結果。

代碼6

='#(\d)#'="abc123"=(,'<font color=red>\1</font>', ;

在子組定義的左括號後面緊跟字符串 ”?:” 會使得該子組不被單獨捕獲, 並且不會對其後子組序號的計算產生影響

 代碼7:匹配數字 把數字改為紅色的

='#.*(?:\d).*([a-z])#U'="3df5g"=(,'<font color=red>\1</font>', ;

如果匹配數字的模式不加?:

那麼

為了方便簡寫,如果需要在非捕獲子組開始位置設置選項, ,比如:

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

 在 PHP 4.3.3 中,

代碼如下8:

="#.*(?<alpha>[a-z]{3})(?'digit'\d{3}).*#"="abc123111def111g"(,,();

結果:

有時需要多個匹配可以在一個正則表達式中選用子組。 為了讓多個子組可以共用一個後向引用數字的問題, (?\語法允許復制數字。 考慮下面的正則表達式匹配Sunday:

(?:(Sat)ur|(Sun))day

這裡當後向引用 1 空時Sun 存儲在後向引用 2 中. 當後向引用 2 不存在的時候 Sat 存儲在後向引用 1中。 使用 (?|修改模式來修復這個問題:

代碼9:

='#(?:(sat)ur|(sun))day#'="sunday saturday"(,,();

結果:

(?|(Sat)ur|(Sun))day

使用這個模式, Sun和Sat都會被存儲到後向引用1中。

在看這個模式前先看以2個下代碼

代碼10-1

$p==

結果是:Array

(
    [0] => Array
        (
            [0] => b2
            [1] => a1
        )

    [1] => Array
        (
            [0] => b
            [1] => a
        )

)
代碼10-2
$p==

結果:

Array
(
    [0] => Array
        (
            [0] => b2
            [1] => a1
        )

    [1] => Array
        (
            [0] => b
            [1] => a
        )

    [2] => Array
        (
            [0] => 
            [1] => a
        )

)
對10-2代碼:
第一次完整匹配到的內容是b2,所以包括匹配內容b的括號即為其第一個子模式是即為b,第二個子模式由於(a)沒有匹配,所以為空
第二次完整匹配到a1,其第一個子模式為a,第二次的由於((a)|b)是外層大括號裡包含的
代碼10-3:
$p==

 

 結果:
Array
(
    [0] => Array
        (
            [0] => b2
            [1] => a1
        )

    [1] => Array
        (
            [0] => b
            [1] => a
        )

    [2] => Array
        (
            [0] => 
            [1] => a
        )

    [3] => Array
        (
            [0] => b
            [1] => 
        )

)

 代碼10-4:

$p==
結果:
Array ( [0] => Array ( [0] => b2 [1] => a1 ) [1] => Array ( [0] => [1] => a ) [2] => Array ( [0] => b [1] => ) )

 

 

代碼10:

='#(?|(sat)ur|(sun))day#'="sunday saturday"(,,();

結果

 

如果緊跟反斜線的數字小於 10, 它總是一個後向引用。模式中的捕獲數要大於等於後向引用的個數

 

後向引用會直接匹配被引用捕獲組在目標字符串中實際捕獲到的內容, 而不是匹配子組模式的內容

 

(sens|respons)e and \1ibility將會匹配 

 

='#(sens|respons)e and \1ibility#'="sense and sensibility response and responsibility  sense and responsibility"(,,();

 

結果

ab(?i)c匹配abC

 

如果在後向引用時被強制進行了大小寫敏感匹配

((?i)abc)\s+\1

匹配 

ABC ABC

AbC AbC

只要兩個一樣不分大小寫

但不匹配 

這裡其實要考慮的是後向引用期望得到的內容是和那個被引用的捕獲子組得到的內容是完全一致的

代碼12:

='#((?i)abc)\s+\1#'="abc abc |ABC ABC  |AbC AbC |abc Abc "(,,();

結果

先看以下代碼13

='#(a|(bc))#'="abc "(,,();

完整匹配了2次

[0][0]是第一次完整的匹配

[1][0]是第一次匹配的第一個子模式

[2][0]是第一次匹配的第二個子模式

[0][1]第二次完整匹配

[1][1]第二次匹配的第一個子模式

[2][1]是第二次匹配的第二個子模式

從上面可以發現對於模式

(a|(bc))

最外面的括號是第一個匹配子模式

裡面的括號裡的是第二個子模式

所以對於以下代碼14:

='#(a|(bc))\2#'="aabcbc"(,,();

結果

當第一匹配

就無從

所以第一次完整匹配中必須得有讓第二個子模式存在的機會即裡面的括號裡的內容必須被匹配到,所以必須得有

因為可能會有多達 99 個後向引用, 所有緊跟反斜線後的數字都可能是一個潛在的後向引用計數。 如果模式在後向引用之後緊接著還是一個數值字符, 那麼必須使用一些分隔符用於終結後向引用語法。

以下代碼15為例:

='#([a-z]{3})\1 5#x'="aaaaaa5"(,,();

模式後向引用\1

我們空下一格,然後在模式修正裡忽略模式裡的空格就能成功匹配

 

 (a\1) 就不會得到任何匹配

而這種引用可以用於內部的子模式重復

(a|b\1)會匹配 ”a”但不會匹配b( 因為子組內部有一個可選路徑,可選路徑中有一條路能夠完成匹配,在匹配完成後, 後向引用就能夠引用到內容了)。

代碼16:

='#(a|b\1)+#'="abba"(,,();

結果

在每次子模式的迭代過程中, 後向引用匹配上一次迭代時這個子組匹配到的字符串。為了做這種工作, 模式必須滿足這樣一個條件,模式在第一次迭代的時候, 必須能夠保證不需要匹配後向引用。 這種條件可以像上面的例子用可選路徑來實現,也可以通過使用最小值為 0 的量詞修飾後向引用的方式來完成。

 

在 PHP 5.2.2之後, g轉義序列可以用於子模式的絕對和相對引用。 這個轉義序列必須緊跟一個無符號數字或一個負數, 可以選擇性的使用括號對數字進行包裹。 序列\1, \g1,\g{1} 之間是同義詞關系。 這種用法可以消除使用反斜線緊跟數值描述反向引用時候產生的歧義。 這種轉義序列有利於區分後向引用和八進制數字字符, 也使得後向引用後面緊跟一個原文匹配數字變的更明了,比如 \g{2}1。

代碼17:

='#([a-z]{2})\g{1}5#'="abab5"(,,();

可與代碼15對比

 

\g 轉義序列緊跟一個負數代表一個相對的後向引用。比如: (foo)(bar)\g{-1} 可以匹配字符串 ”foobarbar”(foo)(bar)\g{-2} 可以匹配 ”foobarfoo”。 這在長的模式中作為一個可選方案, 用來保持對之前一個特定子組的引用的子組序號的追蹤。

代碼18

='#(foo)(bar)\g{-1}#'='#(foo)(bar)\g{-2}#'="foobarbar"="foobarfoo"(,,(,,(();

結果:

後向引用也支持使用子組名稱的語法方式描述, 比如 (?P=name) 或者 PHP 5.2.2 開始可以實用\k<name> 或 \k’name’。 另外在 PHP 5.2.4 中加入了對\k{name} 和 \g{name} 的支持。

代碼19:

="#(?[a-z]{2})(?<digt>[0-9]{3})\k<digt>(?)#"="aa123123aa"(,,();

結果:

可與代碼8比較著看

注意標紅的

Alpha

P

 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved