選擇與編組
選擇允許使用 '|' 字元來在兩個或多個候選項中進行選擇。通過擴充章區段標頭的Regex,可以將其擴充為不僅僅適用於章區段標頭的運算式。不過,這可沒有想象的那麼直接。在使用選擇時,將匹配'|' 字元每邊最可能的運算式。你可能認為下面的 Visual Basic Scripting Edition 和 VBScript 運算式將匹配位於一行的開始和結束位置且後跟一個或兩個數位 'Chapter' 或 'Section':
/^Chapter|Section [1-9][0-9]{0,1}$/"^Chapter|Section [1-9][0-9]{0,1}$"
不幸的是,真正的情況是上面所示的Regex要麼匹配位於一行開始處的單詞 'Chapter',要麼匹配一行結束處的後跟任何數位 'Section'。如果輸入字串為 'Chapter 22',上面的運算式將只匹配單詞 'Chapter'。如果輸入字串為 'Section 22',則該運算式將匹配 'Section 22'。但這種結果不是我們此處的目的,因此必須有一種辦法來使Regex對於所要做的更易於響應,而且確實也有這種方法。
可以使用圓括弧來限制選擇的範圍,也就是說明確該選擇只適用於這兩個單詞 'Chapter' 和 'Section'。不過,圓括弧同樣也是難處理的,因為它們也用來建立子運算式,有些內容將在後面關於子運算式的部分介紹。通過採用上面所示的Regex並在適當位置添加圓括弧,就可以使該Regex既可以匹配 'Chapter 1',也可以匹配 'Section 3'。
下面的Regex使用圓括弧將 'Chapter' 和 'Section' 組成一組,所以該運算式才能正確工作。對 Visual Basic Scripting Edition 為:
/^(Chapter|Section) [1-9][0-9]{0,1}$/
對 VBScript 為:
"^(Chapter|Section) [1-9][0-9]{0,1}$"
這些運算式工作正確,只是產生了一個有趣的副產品。在 'Chapter|Section' 兩邊放置圓括弧建立了適當的編組,但也導致兩個待匹配單詞之一都被捕獲供今後使用。由於在上面所示的運算式中只有一組圓括弧,因此只能有一個捕獲的 submatch。可以使用 VBScript 的Submatches 集合或者Visual Basic Scripting Edition 中RegExp 對象的 $1-$9 屬性來引用這個子匹配。
有時捕獲一個子匹配是所希望的,有時則是不希望的。在說明所示的樣本中,真正想做的就是使用圓括弧對單詞 'Chapter' 或 'Section' 之間的選擇編組。並不希望在後面再引用該匹配。實際上,除非真的是需要捕獲子匹配,否則請不要使用。由於不需要花時間和記憶體來儲存那些子匹配,這種Regex的效率將更高。
可以在Regex模式圓括弧內部的前面使用 '?:'來防止儲存該匹配供今後使用。對上面所示Regex的下述修改提供了免除子匹配儲存的相同功能。對 Visual Basic Scripting Edition:
/^(?:Chapter|Section) [1-9][0-9]{0,1}$/
對 VBScript:
"^(?:Chapter|Section) [1-9][0-9]{0,1}$"
除了 '?:' 元字元,還有兩個非捕獲元字元用於稱之為預查的匹配。一個為正向預查,用 ?= 表示, 在任何開始匹配圓括弧內的Regex模式的位置來匹配搜尋字串。一個為負向預查,用 '?!' 表示,在任何開始不匹配該Regex模式的位置來匹配搜尋字串。
例如,假定有一個包含引用有 Windows 3.1、Windows 95、Windows 98 以及 Windows NT 的文檔。進一步假設需要更新該文檔,方法是尋找所有對 Windows 95、Windows 98 以及 Windows NT 的引用,並將這些引用更改為 Windows 2000。可以使用下面的 Visual Basic Scripting Edition Regex,這是一個正向預查,來匹配 Windows 95、Windows 98 以及 Windows NT:
/Windows(?=95 |98 |NT )/
在 VBScript 要進行同樣的匹配可以使用下述運算式:
"Windows(?=95 |98 |NT )"
找到一個匹配後,緊接匹配到的文字(而不包括預查中使用的字元)就開始對下一次匹配的搜尋。例如,如果上面所示的運算式匹配到 'Windows 98',則將從 'Windows' 而不是 '98' 之後繼續尋找。