[分享] PHP官網對於RegExp小括弧()用法的說明

作者: knuckles (那克斯)   2011-10-10 00:32:35
※ [本文轉錄自 PHP 看板 #1EaPVkLE ]
作者: knuckles (那克斯) 看板: PHP
標題: [分享] PHP官網對於RegExp小括弧()用法的說明
時間: Sun Oct 9 20:47:39 2011
PHP官網寫的好難懂,所以來整理一下自己的心得版
PHP官方網站對於 regular expression 的小括號 () 用法的說明頁
http://www.php.net/manual/en/regexp.reference.subpatterns.php
我自己寫的一點筆記: (網頁上色版 http://disp.cc/b/11.cj-1SO9 )
小括弧有兩種用途:
1. 群組各種可能的子字串,例如 /filename\.(jpg|png|gif)/
這樣就可以找到這三種副檔名的圖檔
2. 標記要取得的字串,例如 /a=(.*?)&b=(.*?)&c=(.*?)&d=/
就可以把 a, b, c 的值分別存到 $1, $2, $3
這兩種用途有時候會混在一起,像是
preg_replace("/((red|white) (king|queen))/","$1, $2, $3","red queen");
← red queen → $1
← red → $2
← queen → $3
會得到 red queen, red, queen
如果只想拿()當群組用,但不要被算進要抓的字串,可以在(後加上 ?:,例如
preg_replace("/((?:red|white) (king|queen))/","$1, $2","red queen");
會得到 red queen, queen (第二個括弧的red不會被抓出來了)
?:中間可以加上選項,例如 i 是忽略大小寫
寫成 (?i:saturday|sunday) 等同於 (?:(?i)saturday|sunday)
可以符合 SUNDAY 或 Saturday,i的效果僅限於這個()
抓到的字串,除了自動依順序配給 $數字 外,也可以自己加上名字
語法 (?P<name>pattern) ,在 PHP5.2.2 另外提供了 (?<name>pattern) 及
(?'name'pattern) 兩種用法
在當群組用時,若每個可能的字串又有用到標記要抓的字串時
例如 (?:(Sat)ur|(Sun))day
用在 Sunday 時,$1="",$2="Sun"
用在 Saturday 時,$1="Sat,$2不存在
此時可以改用 (?|(Sat)ur|(Sun))day
這樣就只會抓到1個字串,$1="Sun" 或 $1="Sat"
至於(?=)、(?!)、(?<=)、(?<!) 是 assertions 的用法
PHP官方網站對於 assertions 的說明
http://www.php.net/manual/en/regexp.reference.assertions.php
我寫的一點筆記: (網頁上色版:http://disp.cc/b/11.cj-2pRT )
Assertion 用來表達位置的符號,不會吃掉字元
例如
^ : 符合整個字串的開頭;在multiline模式,代表一行的開頭
$ : 符合整個字串的結尾;在multiline模式,代表一行的結尾
\b : 符合一個單字邊界(word boundary),一邊是\w一邊是\W
\B : 符合一個非單字邊界,兩邊都是\w 或兩邊都是\W
\A : 只符合整個字串的開頭 (不受multiline模式影響)
\Z : 只符合整個字串的結尾,或是結尾換行前 (不受multiline模式影響)
\z : 只符合整個字串的結尾 (不受multiline模式影響)
\G : 若使用preg_match有設offset時,代表offset的位置,offset為0時就與\A相同
如果是要表達前後是否為某個字串,但不要把這字串抓進來的話,有分為
Lookahead 看後面
(?=abc) : 接下來必需是abc
(?!abc) : 接下來不能是abc
Lookbehind 看前面
(?<=abc) : 前面是接abc
(?<!abc) : 前面不是接abc
舉例
\w+(?=;) 只會抓到後面有接;的\w+,但不會把;抓進來
foo(?!bar) 會抓到所有後面不是接bar的foo
(?!foo)bar 錯誤用法,這樣所有的bar都會抓到
如果想要前面不是接foo的話,要用Lookbehide的用法
(?<!foo)bar 這樣才對,會抓到所有前面不是接foo的bar
可以使用(?<=bullock|donkey)來抓前面是bullock或donkey的字串
但要注意lookbehind的用法時,所有匹配的字串可以分別為不同長度,
但每個必需是固定的長度,例如 (?<!dogs?|cats?) 就不行
要匹配不同長的字串也僅至於最上層的分支,
像 (?<=abc|abde) 可以,但 (?<=ab(c|de)) 就不行
Assertions可以連續使用
例如 (?<=\d{3})(?<!999)foo 可以抓到前面是3個非999數字的foo
注意這兩個assertions都是檢查同一個位置,所以不會抓到前面接6個字元的foo
像 123abcfoo 的foo就不會被抓到,如果要抓像這樣的foo,
要用(?<=\d{3}...)(?<!999)foo
Assertions可以巢狀使用
例如 (?<=(?<!foo)bar)baz 可以抓到 前面是 bar 且 bar 的前面不是 foo 的 baz
例如 (?<=\d{3}...(?<!999))foo 可以抓到 前面是 3個數字與3個非999字元 的foo
作者: PurpleCrow (17868)   0000-00-00 00:00:00
good!
作者: mars90226 (火星人)   0000-00-00 00:00:00
最後一個範例有點不懂...(?<!999)不是要放在某字串之前?了解了!感謝分享!

Links booklink

Contact Us: admin [ a t ] ucptt.com