子組(子模式)

子組通過圓括號(hào)分隔界定,并且它們可以嵌套。 將一個(gè)模式中的一部分標(biāo)記為子組(子模式)主要是來做兩件事情:

  1. 將可選分支局部化。比如,模式cat(arcat|erpillar|)匹配 ”cat”, “cataract”, “caterpillar” 中的一個(gè),如果沒有圓括號(hào)的話,它匹配的則是 ”cataract”, “erpillar” 以及空字符串。

  2. 將子組設(shè)定為捕獲子組(向上面定義的)。當(dāng)整個(gè)模式匹配后, 目標(biāo)字符串中匹配子組的部分將會(huì)通過 pcre_exec()()ovector 參數(shù)回傳給調(diào)用者。 左括號(hào)從左至右出現(xiàn)的次序就是對(duì)應(yīng)子組的下標(biāo)(從 1 開始), 可以通過這些下標(biāo)數(shù)字來獲取捕獲子模式匹配結(jié)果。

比如,如果字符串 ”the red king” 使用模式((red|white) (king|queen)) 進(jìn)行匹配, 模式匹配到的結(jié)果是 array(“red king”, ”red king”, “red”, “king”) 的形式, 其中第 0 個(gè)元素是整個(gè)模式匹配的結(jié)果,后面的三個(gè)元素依次為三個(gè)子組匹配的結(jié)果。 它們的下標(biāo)分別為 1, 2, 3。

事實(shí)上,并不一定同時(shí)需要圓括號(hào)的兩種功能。 經(jīng)常我們會(huì)需要子組進(jìn)行分組, 但又不需要(單獨(dú)的)捕獲它們。 在子組定義的左括號(hào)后面緊跟字符串 ”?:” 會(huì)使得該子組不被單獨(dú)捕獲, 并且不會(huì)對(duì)其后子組序號(hào)的計(jì)算產(chǎn)生影響。比如, 如果字符串 "the white queen" 匹配模式 the ((?:red|white) (king|queen)), 匹配到的子串是 "white queen" 和 "queen", 他們的下標(biāo)分別是 1 和 2。 捕獲子組的最大序號(hào)為 65535。然而由于 libpcre 的配置,我們可能無法編譯這么長(zhǎng)的 正則表達(dá)式。

為了方便簡(jiǎn)寫,如果需要在非捕獲子組開始位置設(shè)置選項(xiàng), 選項(xiàng)字母可以位于 ? 和 : 之間,比如兩個(gè)模式:

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

匹配到了完全相同的字符集。因?yàn)榭蛇x分支會(huì)從左到右嘗試每個(gè)分支, 并且選項(xiàng)沒有在子模式結(jié)束前被重置, 并且由于選項(xiàng)的設(shè)置會(huì)穿透對(duì)后面的其他分支產(chǎn)生影響,因此, 上面的模式都會(huì)匹配 ”SUNDAY” 以及 ”Saturday”。

可以對(duì)子組使用 (?P<name>pattern) 的語法進(jìn)行命名。 這個(gè)子模式將會(huì)在匹配結(jié)果中同時(shí)以其名稱和順序(數(shù)字下標(biāo))出現(xiàn), 還有兩種為子組命名的語法: (?<name>pattern)(?'name'pattern)

有時(shí)需要多個(gè)匹配可以在一個(gè)正則表達(dá)式中選用子組。 為了讓多個(gè)子組可以共用一個(gè)后向引用數(shù)字的問題, (?| 語法允許復(fù)制數(shù)字。 考慮下面的正則表達(dá)式匹配Sunday

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

這里當(dāng)后向引用 1 空時(shí)Sun 存儲(chǔ)在后向引用 2 中。 當(dāng)后向引用 2 不存在的時(shí)候 Sat 存儲(chǔ)在后向引用 1中。 使用 (?|修改模式來修復(fù)這個(gè)問題:

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

使用這個(gè)模式, SunSat 都會(huì)被存儲(chǔ)到后向引用 1 中。