一個(gè)斷言就是一個(gè)對當前匹配位置之前或之后的字符的測試, 它不會(huì )實(shí)際消耗任何字符。簡(jiǎn)單的斷言代碼有\b、\B、 \A、 \Z、\z、 ^、$ 等,在 轉義序列(反斜線(xiàn)) 中有描述。 更加復雜的斷言以子組的方式編碼。 它有兩種類(lèi)型: 前瞻斷言(從當前位置向前測試)和后瞻斷言(從當前位置向后測試)。
一個(gè)斷言子組的匹配還是通過(guò)普通方式進(jìn)行的,
不同在于它不會(huì )導致當前的匹配點(diǎn)發(fā)生改變。
前瞻斷言中的正面斷言(斷言此匹配為真)以 ”(?=” 開(kāi)始,消極斷言以 ”(?!” 開(kāi)頭。比如,
\w+(?=;)
匹配一個(gè)單詞緊跟著(zhù)一個(gè)分號但是匹配結果不會(huì )包含分號,
foo(?!bar)
匹配所有后面沒(méi)有緊跟 ”bar” 的 ”foo” 字符串。
注意一個(gè)類(lèi)似的模式
(?!foo)bar
它不能用于查找之前出現所有不是 ”foo” 的 ”bar” 匹配,
它會(huì )查找到任意的 ”bar” 出現的情況,
因為 (?!foo) 這個(gè)斷言在接下來(lái)三個(gè)字符時(shí) ”bar” 的時(shí)候是永遠都 true
的。
前瞻斷言需要達到的就是這樣的效果。
后瞻斷言中的正面斷言以”(?<=”開(kāi)始, 消極斷言以”(?<!”開(kāi)始。比如,
(?<!foo)bar
用于查找任何前面不是 ”foo” 的 ”bar”。
后瞻斷言的內容被嚴格限制為只能用于匹配定長(cháng)字符串。但是,如果有多個(gè)可選分支,
它們不需要擁有相同的長(cháng)度。比如
(?<=bullock|donkey)
是允許的,
但是
(?<!dogs?|cats?)
將會(huì )引發(fā)一個(gè)編譯期的錯誤。在最上級分支可以匹配不同長(cháng)度的字符串是允許的。
相比較于 perl 5.005 而言,它會(huì )要求多個(gè)分支使用相同長(cháng)度的字符串匹配。
(?<=ab(c|de))
這樣的斷言是不允許的,
因為它單個(gè)的頂級分支可以匹配兩個(gè)不同的長(cháng)度,
但是它可以接受使用兩個(gè)頂級分支的寫(xiě)法
(?<=abc|abde)
這樣的斷言實(shí)現,
對于每個(gè)可選分支,暫時(shí)將當前位置移動(dòng)到嘗試匹配的當前位置之前的固定寬度處。
如果在當前沒(méi)有足夠的字符就視為匹配失敗。后瞻斷言與一次性子組結合使用可以用來(lái)匹配字符串結尾;
一個(gè)例子就是在一次性子組上給出字符串結尾。
多個(gè)斷言(任意順序)可以同時(shí)出現。
比如
(?<=\d{3})(?<!999)foo
匹配前面有三個(gè)數字但不是 ”999” 的字符串 ”foo”。注意,
每個(gè)斷言獨立應用到對目標字符串該點(diǎn)的匹配。 首先它會(huì )檢查前面的三位都是數字,
然后檢查這三位不是 ”999”。
這個(gè)模式不能匹配 ”foo” 前面有三位數字然后緊跟 3 位非 999 共 6 個(gè)字符的字符串,比如,
它不匹配 ”123abcfoo”。
匹配 ”123abcfoo” 這個(gè)字符串的模式可以是
(?<=\d{3}…)(?<!999)foo
。
這種情況下,第一個(gè)斷言查看(當前匹配點(diǎn))前面的 6 個(gè)字符,檢查前三個(gè)是數字, 然后第二個(gè)斷言檢查(當前匹配點(diǎn))前三個(gè)字符不是 ”999”。
斷言可以以任意復雜度嵌套。
比如
(?<=(?<!foo)bar)baz
匹配前面有 ”bar” 但是 ”bar” 前面沒(méi)有 ”foo” 的 ”baz”。
另外一個(gè)模式
(?<=\d{3}...(?<!999))foo
則匹配前面有三個(gè)數字字符緊跟 3 個(gè)不是 999 的任意字符的 ”foo”。
斷言子組時(shí)非捕獲子組,并且不能用量詞修飾, 因為對同一件事做多次斷言是沒(méi)有意義的.如果所有的斷言都包含一個(gè)捕獲子組, 那么為了在整個(gè)模式中捕獲子組計數的目的,它們都會(huì )被計算在內。然而, 子字符串的捕獲僅可以用于正面斷言,因為對于消極的斷言是沒(méi)有意義的。
將斷言計算在內,可以擁有的最大子組數量是 200 個(gè)。