正則表示式:反向引用
正則表示式的最重要功能之一是儲存匹配的模式的一部分以供以後重新使用的能力。您可能想起,若在正則表示式模式或模式的一部分兩側加上括號,就會導致表示式的一部分被儲存到臨時緩衝區中。可以通過使用非捕獲元字元 ?:、?= 或 ?! 來重寫捕獲。
每個捕獲的子匹配項按照它們在正則表示式模式中從左到右出現的順序儲存。緩衝區編號從 1 開始,最多可儲存 99 個捕獲的子表示式。可以使用 \n 來訪問每個緩衝區,其中 n 是標識特定緩衝區的一位或兩位十進位制數字。
反向引用的最簡單的、最有用的應用之一,是提供查詢文字中兩個相同的相鄰單詞的匹配項的能力。以下面的句子為例:
Is is the cost of of gasoline going up up?
上面的句子很顯然有多個重複的單詞。如果能設計一種方法定位該句子,而不必查詢每個單詞的重複出現,那該有多好。下面的正則表示式使用單個子表示式來實現這一點:
/\b([a-z]+) \1\b/gi
捕獲的表示式,正如 [a-z]+ 指定的,包括一個或多個字母。正則表示式的第二部分是對以前捕獲的子匹配項的引用,即,單詞的第二個匹配項正好由括號表示式匹配。\1 指定第一個子匹配項。字邊界元字元確保只檢測整個單詞。否則,諸如“is issued”或“this is”之類的片語將不能正確地被此表示式識別。
正則表示式後面的全域性標記 (g) 指示,將該表示式應用到輸入字串中能夠查詢到的儘可能多的匹配
使用上面的正則表示式,下面的程式碼可以使用子匹配項資訊,將文字字串中的兩個連續相同的單詞的匹配項替換為同一單詞的單個匹配項:
var ss = "Is is the cost of of gasoline going up up?.\n"; var re = /\b([a-z]+) \1\b/gim; //Create regular expression pattern. var rv = ss.replace(re,"$1"); //Replace two occurrences with one.
在 replace 方法內使用 $1 引用第一個儲存的子匹配項。如果您有多個子匹配項,您將通過使用 $2 、$3 等依次引用它們。
反向引用還可以將通用資源指示符 (URI) 分解為其元件。假定您想將下面的 URI 分解為協議(ftp、http 等等)、域地址和頁/路徑:
http://msdn.microsoft.com:80/scripting/default.htm
下面的正則表示式提供該功能:
/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/
第一個括號子表示式捕獲 Web 地址的協議部分。該子表示式匹配在冒號和兩個正斜槓前面的任何單詞。
第二個括號子表示式捕獲地址的域地址部分。該子表示式匹配不包括 / 或 : 字元的任何字元序列。
第三個括號子表示式捕獲埠號(如果指定了的話)。該子表示式匹配冒號後面的零個或多個數字。
最後,第四個括號子表示式捕獲 Web 地址指定的路徑和/或頁資訊。該子表示式匹配 # 或空格字元之外的一個或多個字元。
將正則表示式應用到上面的 URI,各子匹配項包含下面的內容:
- RegExp.$1 包含“http”
- RegExp.$2 包含“msdn.microsoft.com”
- RegExp.$3 包含“:80”
- RegExp.$4 包含“/scripting/default.htm”