RegExp ( 正則表達式 ) 對象

2018-06-16 15:48 更新

 一個 RegExp 對象包含一個正則表達式和關聯的標志。

 正則表達式的格式和功能是以 Perl 5 程序語言的正則表達式設施為藍本的。

模式

 RegExp 構造器對輸入模式字符串應用以下文法。如果文法無法將字符串解釋為 Pattern 的一個展開形式,則發(fā)生錯誤。

 語法:

Pattern :: Disjunction Disjunction :: Alternative Alternative | DisjunctionAlternative :: [empty] Alternative TermTerm :: Assertion Atom Atom QuantifierAssertion :: ^ $ \ b \ B ( ? = Disjunction ) ( ? ! Disjunction )Quantifier :: QuantifierPrefix QuantifierPrefix ?QuantifierPrefix :: * +  ? { DecimalDigits } { DecimalDigits , } { DecimalDigits , DecimalDigits }Atom :: PatternCharacter . \ AtomEscape CharacterClass ( Disjunction ) ( ? : Disjunction ) PatternCharacter :: SourceCharacter but not any of: ^ $ \ . * + ? ( ) [ ] { } | AtomEscape :: DecimalEscape CharacterEscape CharacterClassEscapeCharacterEscape :: ControlEscape c ControlLetter HexEscapeSequence UnicodeEscapeSequence IdentityEscape ControlEscape :: one of f n r t v ControlLetter :: one of a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z IdentityEscape :: SourceCharacter but not IdentifierPart DecimalEscape :: DecimalIntegerLiteral [lookahead ? DecimalDigit] CharacterClassEscape :: one of d D s S w W CharacterClass :: [ [lookahead ? {^}] ClassRanges ] [ ^ ClassRanges ]ClassRanges :: [empty] NonemptyClassRangesNonemptyClassRanges :: ClassAtom ClassAtom NonemptyClassRangesNoDash ClassAtom - ClassAtom ClassRangesNonemptyClassRangesNoDash :: ClassAtom ClassAtomNoDash NonemptyClassRangesNoDash ClassAtomNoDash - ClassAtom ClassRangesClassAtom :: - ClassAtomNoDashClassAtomNoDash :: SourceCharacter but not one of \ or ] or - \ ClassEscapeClassEscape :: DecimalEscape b CharacterEscape CharacterClassEscape

模式語義

 使用下面描述的過程來將一個正則表達式模式轉換為一個內部程序。實現使用比下面列出的算法跟高效的算法是被鼓勵的,只要結果是相同的。內部程序用作 RegExp 對象的 [[Match]] 內部屬性的值。

表示法

 后面的描述用到以下變量:

  • input,是正則表達式模式要匹配的字符串。符號 input[n] 表示 input 的第 n 個字符,這里的 n 可以是 0( 包括 ) 和 InputLength( 不包括 ) 之間的。
  • InputLength,是 input 字符串里的字符數目。
  • NcapturingParens,是在模式中左捕獲括號的總數 ( 即,Atom :: ( Disjunction ) 產生式被展開的總次數 )。一個左捕獲括號是匹配產生式 Atom :: ( Disjunction ) 中的 終結符 ( 的任意 ( 模式字符。
  • IgnoreCase,是 RegExp 對象的 ignoreCase 屬性的設定值。
  • Multiline,是 RegExp 對象的 multiline 屬性的設定值。

 此外,后面的描述用到以下內部數據結構:

  • CharSet,是字符的一個數學上的集合。
  • State,是一個有序對 (endIndex, captures) ,這里 endIndex 是一個整數,captures 是有 NcapturingParens 個值的內部數組。 States 用來表示正則表達式匹配算法里的局部匹配狀態(tài)。endIndex 是到目前為止模式匹配的最后一個輸入字符的索引值加上一,而 captures 持有捕獲括號的捕獲結果。captures 的第 n 個元素是一個代表第 n 個捕獲括號對捕獲值的字符串,或如果第 n 個捕獲括號對未能達到目的,captures 的第 n 個元素是 undefined。由于回溯,很多 States 可能在匹配過程中的任何時候被使用。
  • MatchResult,值為 State 或表示匹配失敗特殊 token--failure。
  • Continuation 程序,是一個內部閉包(即,一些參數已經綁定了值的內部程序),它用一個 State 參數返回一個 MatchResult 結果。 如果一個內部閉包引用的變量是綁定在創(chuàng)建這個閉包的函數里 , 則閉包使用在創(chuàng)建閉包時的這些變量值。Continuation 嘗試從其 State 參數給定的中間狀態(tài)開始用模式的其余部分(由閉包的已綁定參數指定)匹配輸入字符串。如果匹配成功,Continuation 返回最終的 State;如果匹配失敗,Continuation 返回 failure。
  • Matcher 程序,是一個需要兩個參數 -- 一個 State 和一個 Continuation -- 的內部閉包,它返回一個 MatchResult 結果。 Matcher 嘗試從其 State 參數給定的中間狀態(tài)開始用模式的一個中間子模式(由閉包的已綁定參數指定)匹配輸入字符串。Continuation 參數是去匹配模式中剩余部分的閉包。用模式的子模式匹配之后獲得一個新 State,之后 Matcher 用新 State 去調用 Continuation 來測試模式的剩余部分是否能匹配成功。如果匹配成功,matcher 返回 Continuation 返回的 State;如果匹配失敗,Matcher 嘗試用不同的可選位置重復調用 Continuation,直到 Continuation 匹配成功或用盡所有的可選位置。
  • AssertionTester 程序,是需要一個 State 參數并返回一個布爾結果的內部閉包。 AssertionTester 測試輸入字符串的當前位置是否滿足一個特定條件 ( 由閉包的已綁定參數指定 ) ,如果匹配了條件,返回 true;如果不匹配,返回 false。
  • EscapeValue,是一個字符或一個整數。EscapeValue 用來表示 DecimalEscape 轉移序列的解釋結果:一個字符 ch 在轉義序列里時,它被解釋為字符 ch;而一個整數 n 在轉義序列里時,它被解釋為對第 n 個捕獲括號組的反響引用。

模式(Pattern)

 產生式 Pattern :: Disjunction 按照以下方式解釋執(zhí)行 :

  1. 解釋執(zhí)行 Disjunction ,獲得一個 Matcher m.
  2. 返回一個需要兩個參數的內部閉包,一個字符串 str 和一個整數 index, 執(zhí)行方式如下 :令 Input 為給定的字符串 str。15.10.2 中的算法都將用到此變量。令 InputLength 為 Input 的長度。15.10.2 中的算法都將用到此變量。令 c 為 一個 Continuation ,它始終對它的任何 State 參數都返回成功匹配的 MatchResult。令 cap 為一個有 NcapturingParens 個 undefined 值的內部數組,索引是從 1 到 NcapturingParens。令 x 為 State (index, cap).調用 m(x, c),并返回結果 .

 一個模式解釋執(zhí)行(“編譯”)為一個內部程序值。RegExp.prototype.exec 可將這個內部程序應用于一個字符串和字符串的一個偏移位,來確定從這個偏移位開始 , 模式是否能夠匹配,如果能匹配,將返回捕獲括號的值。15.10.2 中的算法被設計為只在編譯一個模式時可拋出一個 SyntaxError 異常;反過來說,一旦模式編譯成功,應用編譯生成的內部程序在字符串中尋找匹配結果時不可拋出異常(除非是宿主定義的可在任何時候出現的異常,如內存不足)。

析取(Disjunction)

 產生式 Disjunction :: Alternative 的解釋執(zhí)行,是解釋執(zhí)行 Alternative 來獲得 Matcher 并返回這個 Matcher。

 產生式 Disjunction :: Alternative | Disjunction 按照以下方式解釋執(zhí)行:

  1. 解釋執(zhí)行 Alternative 來獲得一個 Matcher m1.
  2. 解釋執(zhí)行 Disjunction 來獲得一個 Matcher m2.
  3. 返回一個需要兩個參數的內部閉包 Matcher ,參數分別是一個 State x 和一個 Continuation c,此內部閉包的執(zhí)行方式如下:調用 m1(x, c) 并令 r 為其結果。如果 r 不是 failure, 返回 r.調用 m2(x, c) 并返回其結果。

 正則表達式運算符 | 用來分隔兩個選擇項。模式首先嘗試去匹配左側的 Alternative( 緊跟著是正則表達式的后續(xù)匹配結果 );如果失敗,嘗試匹配右側的 Disjunction(緊跟著是正則表達式的后續(xù)匹配結果)。如果左側的 Alternative,右側的 Disjunction,還有后續(xù)匹配結果,全都有可選的匹配位置,則后續(xù)匹配結果的所有可選位置是在左側的 Alternative 移動到下一個可選位置之前確定的。如果左側 Alternative 的可選位置被用盡了,右側 Disjunction 試圖替代左側 Alternative。一個模式中任何被 | 跳過的捕獲括號參數 undefined 值還代替字符串。因此,如:

/a|ab/.exec("abc")

 返回結果是 "a",而不是 "ab"。此外

/((a)|(ab))((c)|(bc))/.exec("abc")

 返回的數組是

["abc", "a", "a", undefined, "bc", undefined, "bc"]

 而不是

["abc", "ab", undefined, "ab", "c", "c", undefined]

選擇項(Alternative)

 產生式 Alternative :: [empty] 解釋執(zhí)行返回一個 Matcher,它需要兩個參數,一個 State x 和 一個 Continuation c,并返回調用 c(x) 的結果。

 產生式 Alternative :: Alternative Term 按照如下方式解釋執(zhí)行:

  1. 解釋執(zhí)行 Alternative 來獲得一個 Matcher m1.
  2. 解釋執(zhí)行 Term 來獲得一個 Matcher m2.
  3. 返回一個內部閉包 Matcher,它需要兩個參數,一個 State x 和一個 Continuation c, 執(zhí)行方式如下 :創(chuàng)建一個 Continuation d ,它需要一個 State 參數 y ,返回調用 m2(y, c) 的結果 .調用 m1(x, d) 并返回結果 .

 連續(xù)的 Term 試著同時去匹配連續(xù)輸入字符串的連續(xù)部分。如果左側的 Alternative,右側的 Term,還有后續(xù)匹配結果,全都有可選的匹配位置,則后續(xù)匹配結果的所有可選位置是在右側的 Term 移動到下一個可選位置之前確定的,并且則右側的 Term 的所有可選位置是在左側的 Alternative 移動到下一個可選位置之前確定的。

匹配項(Term)

 產生式 Term :: Assertion 解釋執(zhí)行,返回一個需要兩個參數 State x 和 Continuation c 的內部閉包 Matcher,它的執(zhí)行方式如下:

  1. 解釋執(zhí)行 Assertion 來獲得一個 AssertionTester t.
  2. 調用 t(x) 并令 r 為調用結果布爾值 .
  3. 如果 r 是 false, 返回 failure.
  4. 調用 c(x) 并返回結果 .

 產生式 Term :: Atom 的解釋執(zhí)行方式是,解釋執(zhí)行 Atom 來獲得一個 Matcher 并返回這個 Matcher。

 產生式 Term :: Atom Quantifier 的解釋執(zhí)行方式如下 :

  1. 解釋執(zhí)行 Atom 來獲得一個 Matcher m.
  2. 解釋執(zhí)行 Quantifier 來獲得三個結果值:一個整數 min, 一個整數 ( 或 ∞) max, 和一個布爾值 greedy.
  3. 如果 max 是有限的 且小于 min, 則拋出一個 SyntaxError 異常 .
  4. 令 parenIndex 為整個正則表達式中在此產生式 Term 展開形式左側出現的左匹配括號的數目。這是此產生式 Term 前面展開的 Atom :: ( Disjunction ) 產生式總數與此 Term 里面的 Atom :: ( Disjunction ) 產生式總數之和。
  5. 令 parenCount 為在展開的 Atom 產生式里的左捕獲括號數目。這是 Atom 產生式里面 Atom :: ( Disjunction ) 產生式的總數。
  6. 返回一個需要兩個參數 State x 和 Continuation c 的內部閉包 Matcher,執(zhí)行方式如下 :調用 RepeatMatcher(m, min, max, greedy, x, c, parenIndex, parenCount) ,并返回結果 .

 抽象操作 RepeatMatcher 需要八個參數,一個 Matcher m, 一個整數 min, 一個整數 ( 或 ∞) max, 一個布爾值 greedy, 一個 State x, 一個 Continuation c, 一個整數 parenIndex, 一個整數 parenCount, 執(zhí)行方式如下 :

  1. 如果 max 是零 , 則調用 c(x) ,并返回結果 .
  2. 創(chuàng)建需要一個 State 參數 y 的內部 Continuation 閉包 d ,執(zhí)行方式如下 :如果 min 是零 且 y 的 endIndex 等于 x 的 endIndex, 則返回 failure.如果 min 是零,則令 min2 為零 ; 否則令 min2 為 min–1.如果 max 是 ∞, 則令 max2 為 ∞; 否則令 max2 為 max–1.調用 RepeatMatcher(m, min2, max2, greedy, y, c, parenIndex, parenCount) ,并返回結果 .
  3. 令 cap 為 x 的捕獲內部數組的一個拷貝。
  4. 對所有滿足條件 parenIndex < k 且 k ≤ parenIndex+parenCount 的整數 k,設定 cap[k] 為 undefined。
  5. 令 e 為 x 的 endIndex.
  6. 令 xr 為 State 值 (e, cap).
  7. 如果 min 不是零 , 則調用 m(xr, d),并返回結果 .
  8. 如果 greedy 是 false, 則令 z 為調用 c(x) 的結果 .如果 z 不是 failure, 返回 z.調用 m(xr, d),并返回結果 .
  9. 令 z 為調用 m(xr, d) 的結果 .
  10. 如果 z 不是 failure, 返回 z.
  11. 調用 c(x) ,并返回結果 .

 一個Atom后跟Quantifier是用Quantifier指定重復的次數。Quantifier可以是非貪婪的,這種情況下Atom模式在能夠匹配序列的情況下盡可能重復少的次數, 或者它可以使貪婪的,這種情況下Atom模式在能夠匹配序列的情況下盡可能重復多的次數,Atom模式重復的是他自己而不是它匹配的字符串,所以不同次的重復中Atom可以匹配不同的子串。

 假如Atom和后續(xù)的正則表達式都有選擇余地,Atom首先盡量多匹配(或者盡量少,假如是非貪婪模式)在最后一次Atom的重復中移動到下一個選擇前,所有的后續(xù)中的選項<都應該被嘗試。 在倒數第二次(第n–1次)Atom的重復中移動到下一個選擇前,所有Atom的選項在最后一次(第n次)重復中應該被嘗試。這樣可以得出更多或者更少的重復次數可行。 這些情況在開始匹配下一個選項的第(n-1)次重復時已經被窮舉,以此類推。

 比較

/a[a-z]{2,4}/.exec("abcdefghi")

 它返回"abcde"而

/a[a-z]{2,4}?/.exec("abcdefghi")

 它返回"abc".

 再考慮

/(aa|aabaac|ba|b|c)*/.exec("aabaac")

 按照上面要求的選擇數,它返回

["aaba", "ba"]

 而非以下:

["aabaac", "aabaac"] ["aabaac", "c"]

 上面要求的選擇數可以用來編寫一個計算兩個數最大公約數的正則表達式(用單一字符重復數表示). 以下實例用來計算10和15的最大公約數:

"aaaaaaaaaa,aaaaaaaaaaaaaaa".replace(/^(a+)\1*,\1+$/,"$1")

 它返回最大公約數的單一字符重復數表示"aaaaa".

 RepeatMatcher的步驟4 每重復一次就清除Atom的捕獲。我們可以看到它在正則表達式中的行為:

/(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac")

 它返回數組

["zaacbbbcac", "z", "ac", "a", undefined, "c"]

 而非

["zaacbbbcac", "z", "ac", "a", "bbb", "c"]

 因為最外面的*每次迭代都會清除所有括起來的Atom中所含的捕獲字符串,在這個例子中就是包含編號為2,3,4,5的捕獲字符串。

 RepeatMatcher的d閉包狀態(tài)步驟1,一旦重復的最小次數達到,任何Atom匹配空String的擴展不再會匹配到重復中。這可以避免正則引擎在匹配類似下面的模式時掉進無限循環(huán):

/(a*)*/.exec("b")

 或者稍微復雜一點:

/(a*)b\1+/.exec("baaaac")

 它返回數組:

["b", ""]

Assertion

 產生式Assertion :: ^ 解釋執(zhí)行返回一個 AssertionTester , 它需要1個參數 State x,并按如下算法執(zhí)行:

  1. 使 e 為 x的 endIndex
  2. 若 e = 0, 返回 true
  3. 若 Multiline 為 false,返回false
  4. 若 Input[e - 1] 的字符為 LineTerminator,返回 true
  5. 返回false

 產生式Assertion :: $ 解釋執(zhí)行返回一個 AssertionTester , 它需要1個參數 State x,并按如下算法執(zhí)行:

  1. 使 e 為 x的 endIndex
  2. 若 e = InputLength, 返回 true
  3. 若 Multiline 為 false,返回false
  4. 若 Input[e - 1] 的字符為 LineTerminator,返回 true
  5. 返回false

 產生式Assertion :: \ b 解釋執(zhí)行返回一個 AssertionTester , 它需要1個參數 State x,并按如下算法執(zhí)行:

  1. 使 e 為 x的 endIndex
  2. 調用IsWordChar(e–1),返回Boolean值賦給a
  3. 調用IsWordChar(e),返回Boolean值賦給b
  4. 若 a 為true,b為false,返回true
  5. 若 b 為false,b為true,返回true
  6. 若 Input[e - 1] 的字符為 LineTerminator,返回 true
  7. 返回false

 產生式Assertion :: \ B 解釋執(zhí)行返回一個 AssertionTester , 它需要1個參數 State x,并按如下算法執(zhí)行:

  1. 使 e 為 x的 endIndex
  2. 調用IsWordChar(e–1),返回Boolean值賦給a
  3. 調用IsWordChar(e),返回Boolean值賦給b
  4. 若 a 為true,b為false,返回false
  5. 若 b 為false,b為true,返回false
  6. 若 Input[e - 1] 的字符為 LineTerminator,返回 true
  7. 返回true

 產生式Assertion :: (? = Disjunction) 按如下算法執(zhí)行:

  1. 執(zhí)行Disjunction ,得到 Matcher m
  2. 返回一個需要兩個參數的內部閉包 Matcher ,參數分別是一個 State x 和一個 Continuation c,此內部閉包的執(zhí)行方式如下::使 d 為一個Continuation,它始終對它的任何 State 參數都返回成功匹配的 MatchResult調用m(x, d),令r為其結果若r為failure,返回 failure使y 為 r的State使cap 為 r的captures使xe為 r的endIndex使z為 State (xe, cap)調用c(z),返回結果

 產生式Assertion :: (? ! Disjunction) 按如下算法執(zhí)行:

  1. 執(zhí)行Disjunction ,得到 Matcher m
  2. 返回一個需要兩個參數的內部閉包 Matcher ,參數分別是一個 State x 和一個 Continuation c,此內部閉包的執(zhí)行方式如下::使 d 為一個Continuation,它始終對它的任何 State 參數都返回成功匹配的 MatchResult調用m(x, d),令r為其結果若r為failure,返回 failure調用c(z),返回結果

 抽象操作 IsWordChar ,擁有一個integer類型的參數e,按如下方式執(zhí)行:

  1. 若 e == -1 或 e == InputLength,返回 false
  2. 令 c 為 Input[e]
  3. 若 c 為 以下63個字符,返回 true

 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 _

  1. 返回 false

Quantifier

 產生式 Quantifier :: QuantifierPrefix 按如下方式執(zhí)行:

  1. 執(zhí)行 QuantifierPrefix 得到 2個數 min 和 max(或 ∞)
  2. 返回 min,max,true

 產生式 Quantifier :: QuantifierPrefix ? 按如下方式執(zhí)行:

  1. 執(zhí)行 QuantifierPrefix 得到 2個數 min 和 max(或 ∞)
  2. 返回 min,max,true

 產生式 Quantifier :: * 返回 0 和 ∞

 產生式 Quantifier :: + 返回 1 和 ∞

 產生式 Quantifier :: ? 返回 0 和 1

 產生式 Quantifier :: { DecimalDigits } 按如下方式執(zhí)行:

  1. 令 i 為 DecimalDigits 的 MV
  2. 返回2個結果 i,i

 產生式 Quantifier :: { DecimalDigits, } 按如下方式執(zhí)行:

  1. 令 i 為 DecimalDigits 的 MV
  2. 返回2個結果 i,∞

 產生式 Quantifier :: { DecimalDigits, DecimalDigits} 按如下方式執(zhí)行:

  1. 令 i 為 DecimalDigits 的 MV
  2. 令 j 為 DecimalDigits 的 MV
  3. 返回2個結果 i,j

Atom

 產生式 Atom :: PatternCharacter 執(zhí)行方式如下:

  1. 令 ch 為 PatternCharacter表示的字符
  2. 令 A 為單元素 CharSet,包含ch
  3. 調用 CharacterSetMatcher(A, false),返回Matcher

 產生式 Atom :: . 執(zhí)行方式如下:

  1. 令 A為 除去 LineTerminator外的所有字符
  2. 調用 CharacterSetMatcher(A, false),返回Matcher

 產生式 Atom :: \ AtomEscape 通過執(zhí)行 AtomEscape 返回 Matcher。

 產生式 Atom :: CharacterClass 執(zhí)行方式如下:

  1. 執(zhí)行 CharacterClass 得到 CharSet A 和 Boolean invert
  2. 調用 CharacterSetMatcher(A, false),返回Matcher

 產生式 Atom :: ( Disjunction ) 執(zhí)行方式如下:

  1. 執(zhí)行 Disjunction 得到 Matcher
  2. 令 parenIndex 為 在整個正則表達式中從產生式展開初始化左括號時,當前展開左捕獲括號的索引。parenIndex 為在產生式的 Atom 被展開之前,Atom :: ( Disjunction )產生式被展開的次數,加上Atom :: ( Disjunction ) 閉合 這個Atom的次數
  3. 返回一個內部閉包 Matcher,擁有2個參數:一個 State x 和 Continuation c,執(zhí)行方式如下:創(chuàng)建內容閉包 Continuation d,參數為State y,并按如下方式執(zhí)行:令cap為y的capture數組的一個拷貝令xe為x的endIndex令ye為y的endIndex令s為Input從索引xe(包括)至 ye(不包括)范圍的新創(chuàng)建的字符串令s為cap[parenIndex+1]令z為 State (ye, cap)調用c(z),返回其結果執(zhí)行m(x, d),返回其結果

 產生式 Atom :: ( ? : Disjunction ) 通過執(zhí)行Disjunction 得到并返回一個Matcher。

 抽象操作 CharacterSetMatcher ,擁有2個參數:一個 CharSet A 和 Boolean invert標志,按如下方式執(zhí)行:

  1. 返回一個內部閉包 Matcher,擁有2個參數:一個 State x 和 Continuation c,執(zhí)行方式如下:令e為x的endIndex若e == InputLength,返回failure令ch為字符Input[e]令cc為Canonicalize(ch)的結果若invert為false,如果A中不存在a使得Canonicalize(a) == cc,返回failure若invert為true,如果A中存在a使得Canonicalize(a) == cc, 返回failure令cap為x的內部captures數組令y為 State (e+1, cap)調用c(y),返回結果

 抽象操作 Canonicalize,擁有一個字符參數 ch,按如下方式執(zhí)行:

  1. 若IgnoreCase為false,返回ch
  2. 令u為ch轉換為大寫后的結果,仿佛通過調用標準內置方法String.prototype.toUpperCase
  3. 若u不含單個字符,返回ch
  4. 令cu為u的字符
  5. 若ch的code unit value>= 128 且 cu的code unit value<= 128,返回ch
  6. 返回cu

 ( Disjunction ) 的括號 用來組合 Disjunction 模式,并保存匹配結果。該結果可以通過后向引用(一個非零數,前置\),在一個替換字符串中的引用,或者作為正則表達式內部匹配過程的部分結果。使用(?: Disjunction )來避免括號的捕獲行為。

 (? = Disjunction )指定一個零寬正向預查。為了保證匹配成功,其 Disjunction 必須首先能夠匹配成功,但在匹配后續(xù)字符前,其當前位置會不變。如果 Disjunction 能在當前位置以多種方式匹配,那么只會取第一次匹配的結果。不像其他正則表達式運算符,(?= 內部不會回溯(這個特殊的行為是從Perl繼承過來的)。在 Disjunction 含有捕獲括號,模式的后續(xù)字符包括后向引用時匹配結果會有影響。

 例如,

/(?=(a+))/.exec("baaabac")

 會匹配第一個b后的空白字符串,得到:

["", "aaa"]

 為了說明預查不會回溯,

/(?=(a+))a*b\1/.exec("baaabac")

 得到:

["aba", "a"]

 而不是:

["aaaba", "a"]

 (?! Disjunction ) 指定一個零寬正向否定預查。為了保證匹配成功,其 Disjunction 必須首先能夠匹配失敗,但在匹配后續(xù)字符前,其當前位置會不變。Disjunction 能含有捕獲括號,但是對這些捕獲分組的后向引用只在Disjunction中有效。在當前模式的其他位置后向引用捕獲分組都會返回undefined。因為否定預查必須滿足預查失敗來保證模式成功匹配。例如,

/(.*?)a(?!(a+)b\2c)\2(.*)/.exec("baaabaac")

 搜索a,其后有n個a,一個b,n個a(\2指定)和一個c。第二個\2位于負向預查模式的外部,因此它匹配undefined,且總是成功的。整個表達式返回一個數組:

["baaabaac", "ba", undefined, "abaac"]

 在發(fā)生比較前,一次不區(qū)分大小寫的匹配中所有的字符都會隱式轉換為大寫。然而,如果某些單個字符在轉換為大寫時擴展為多個字符,那么該字符會保持原樣。當某些非ASCII字符在轉換為大寫時變成ASCII字符,該字符也會保持原樣。這樣會阻止Unicode字符(例如\u0131和\u017F)匹配正則表達式 (例如僅匹配ASCII字符的正則表達式/[a z]/i)。而且,如果轉換允許,/[^\W]/i會匹配除去i或s外的每一個a,b,......,h。

AtomEscape

 產生式 AtomEscape :: DecimalEscape 執(zhí)行方式如下:

  1. 執(zhí)行DecimalEscape得到 EscapeValue E
  2. 如果E為一個字符,令ch為E的字符令A為包含ch字符的單元素字符集CharSet調用 CharacterSetMatcher(A, false) 返回Matcher結果
  3. E必須是一個數。令n為該數。
  4. 如果n=0或n>NCapturingParens,拋出 SyntaxError 異常
  5. 返回一個內部閉包 Matcher,擁有2個參數:一個 State x 和 Continuation c,執(zhí)行方式如下:令cap為x的captures內部數組令s為cap[n]如果s為undefined,調用c(x),返回結果令e為x的endIndex令len為s的length令f為e+len如果f>InputLength,返回failure如果存在位于0(包括)到len(不包括)的整數i使得 Canonicalize(s[i])等于 Canonicalize(Input [e+i]),那么返回failure令y為State(f, cap)調用c(y),返回結果

 產生式 AtomEscape :: CharacterEscape 執(zhí)行方式如下:

  1. 執(zhí)行CharacterEscape 得到一個ch字符
  2. 令A為包含ch字符的單元素字符集CharSet
  3. 調用 CharacterSetMatcher(A, false) 返回Matcher結果

 產生式 AtomEscape :: CharacterClassEscape 執(zhí)行方式如下:

  1. 執(zhí)行CharacterClassEscape 得到一個CharSet A
  2. 調用 CharacterSetMatcher(A, false) 返回Matcher結果

 格式\后為非零數n的轉義序列匹配捕獲分組的第n次匹配結果。如果正則表達式少于n個捕獲括號,會報錯。如果正則表達式大于等于n個捕獲括號,由于沒有捕獲到任何東西,導致第n個捕獲分組結果為undefined,那么后向引用總是成功的。

CharacterEscape

 產生式 CharacterEscape :: ControlEscape 執(zhí)行返回一個根據表23定義的字符:

ControlEscape字符轉義值
ControlEscape字符編碼值名稱符號
t\u0009水平制表符<HT>
n\u000A進行(新行)<LF>
v\u000B豎直制表符<VT>
f\u000C進紙<FF>
r\u000D回車<CR>

 產生式 CharacterEscape :: ch ControlLetter 執(zhí)行過程如下:

  1. 令ch為通過ControlLetter表示的字符
  2. 令i為ch的code unit value
  3. 令j為i/32的余數
  4. 返回j

 產生式 CharacterEscape :: HexEscapeSequence 執(zhí)行HexEscapeSequence的CV,返回其字符結果。

 產生式 CharacterEscape :: UnicodeEscapeSequence 執(zhí)行UnicodeEscapeSequence的CV,返回其字符結果。

 產生式 CharacterEscape :: IdentityEscape執(zhí)行返回由IdentityEscape表示的字符。

DecimalEscape

 產生式 DecimalEscape :: DecimalIntegerLiteral [lookahead ? DecimalDigit] 按如下方式執(zhí)行:

  1. 令i為DecimalIntegerLiteral的CV值
  2. 如果i為0,返回包含一個<NUL>字符(Unicode值為0000)的EscapeValue
  3. 返回包含整數i的EscapeValue

 “the MV of DecimalIntegerLiteral”在7.8.3節(jié)定義。

 如果\后面是一個數字,且首位為0,那么,該轉義序列被認為是一個后向引用。如果n比在整個正則表達式左捕獲括號個數大,那么會出錯。\0 表示 <NUL>字符,其后不能再有數字。

CharacterClassEscape

 產生式 CharacterClassEscape :: d執(zhí)行返回包含0到9之間的十元素字符集。

 產生式 CharacterClassEscape :: D執(zhí)行返回不包括 CharacterClassEscape :: d的字符集。

 產生式 CharacterClassEscape :: s執(zhí)行返回包含 WhiteSpace 或 LineTerminator 產生式右部分字符的字符集。

 產生式 CharacterClassEscape :: S執(zhí)行返回不包括 CharacterClassEscape :: s的字符集。

 產生式 CharacterClassEscape :: w執(zhí)行返回包含如下63個字符的字符集:

 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 _

 產生式 CharacterClassEscape :: W執(zhí)行返回不包括CharacterClassEscape :: w的字符集。

CharacterClass

 產生式 CharacterClass :: [ [lookahead ? {^}] ClassRanges ] 通過執(zhí)行ClassRanges獲得并返回這個CharSet和Boolean false。

 產生式 CharacterClass :: [ ^ ClassRanges ] 通過執(zhí)行ClassRanges獲得并返回這個CharSet和Boolean true。

ClassRanges

 產生式 ClassRanges :: [empty]執(zhí)行返回一個空的CharSet。

 產生式 ClassRanges :: NonemptyClassRanges 通過執(zhí)行 NonemptyClassRanges 獲得并返回這個CharSet。

NonemptyClassRanges

 產生式 NonemptyClassRanges :: ClassAtom 通過執(zhí)行ClassAtom獲得一個CharSet并返回這個CharSet。

 產生式 NonemptyClassRanges :: ClassAtom NonemptyClassRangesNoDash 按如下方式執(zhí)行:

  1. 執(zhí)行 ClassAtom 得到一個CharSet A
  2. 執(zhí)行 NonemptyClassRangesNoDash 得到一個CharSet B
  3. 返回A與B的并集

 產生式 NonemptyClassRanges :: ClassAtom - ClassAtom ClassRanges 按如下方式執(zhí)行:

  1. 執(zhí)行第一個ClassAtom 得到一個CharSet A
  2. 執(zhí)行第二個ClassAtom 得到一個CharSet B
  3. 執(zhí)行ClassRanges 得到一個CharSet C
  4. 調用 CharacterRange(A, B),令D為其結果CharSet
  5. 返回D與C的并集

 抽象操作 CharacterRange,擁有2個CharSet參數A和B,執(zhí)行方式如下:

  1. 如果A或B為空,拋出SyntaxError異常
  2. 令a為CharSet A的一個字符
  3. 令b為CharSet B的一個字符
  4. 令i為a的code unit value
  5. 令j為b的code unit value
  6. 如果i>j,拋出SyntaxError異常
  7. 返回位于在i到j(包括邊界)之間的所有字符的字符集

NonemptyClassRangesNoDash

 產生式NonemptyClassRangesNoDash :: ClassAtom 執(zhí)行過程是執(zhí)行ClassAtom產生一個CharSet并且返回這個CharSet。

 產生式NonemptyClassRangesNoDash :: ClassAtomNoDash NonemptyClassRangesNoDash 按以下方式執(zhí)行:

  1. 執(zhí)行ClassAtomNoDash產生CharSet A
  2. 執(zhí)行NonemptyClassRangesNoDash產生CharSet B
  3. 返回CharSet A和B的并集

 產生式NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassRanges 按以下方式執(zhí)行:

  1. 執(zhí)行ClassAtomNoDash產生CharSet A
  2. 執(zhí)行ClassAtom產生CharSet B
  3. 執(zhí)行ClassRanges產生CharSet C
  4. 調用CharacterRange(A, B)并設CharSet D為結果。
  5. 返回CharSet D和C的并集

 ClassRanges可以拆分成單獨的ClassAtom且/或兩個用減號分隔的ClassAtom。在后面的情況下ClassAtom包含第一個到第二個ClassAtom間的所有字符。 如果兩個ClassAtom之一不是表示一個單獨字符(例如其中一個是\w)或者第一個ClassAtom的字符編碼值比第二個ClassAtom的字符編碼值大則發(fā)生錯誤。

 即使匹配忽略大小寫,區(qū)間兩端的大小寫在區(qū)分哪些字符屬于區(qū)間時仍然有效。這意味著,例如模式/[E-F]/僅僅匹配E, F, e, 和 f。/[E-f]/i則匹配所有大寫和小寫的ASCII字母以及[, \, ], ^, _, 和 `

 -字符可能被當做字面意思或者表示一個區(qū)間,它作為ClassRange的開頭或者結尾、在區(qū)間指定開頭或者結尾,或者緊跟一個區(qū)間指定的時候被當做字面意思。

ClassAtom

 產生式 ClassAtom :: - 執(zhí)行返回包含單個字符 - 的字符集。

 產生式 ClassAtom :: ClassAtomNoDash 通過執(zhí)行 ClassAtomNoDash 獲得并返回這個 CharSet。

ClassAtomNoDash

 產生式 ClassAtomNoDash :: SourceCharacter 不包括\,],- 執(zhí)行返回包含由 SourceCharacter 表示的字符的單元素字符集。

 產生式 ClassAtomNoDash :: \ ClassEscape 通過執(zhí)行ClassEscape 得到并返回這個CharSet。

ClassEscape

 產生式 ClassEscape :: DecimalEscape 按如下方式執(zhí)行:

  1. 執(zhí)行 DecimalEscape 得到 EscapeValue E
  2. 如果E不是一個字符,拋出 SyntaxError異常
  3. 令ch為E的字符
  4. 返回包含字符ch的單元素CharSet

 產生式 ClassEscape :: b 執(zhí)行返回包含一個<BS>字符(Unicode值0008)的字符集。

 產生式 ClassEscape :: CharacterEscape 通過執(zhí)行 CharacterEscape 獲得一個字符Charset并返回包含該字符的單元素字符集CharSet。

 產生式 ClassEscape :: CharacterClassEscape 通過執(zhí)行 CharacterClassEscape 獲得并返回這個CharSet。

 ClassAtom 可以使用除\b,\B,后向引用外的轉義序列。在CharacterClass中,\b表示退格符。然而,\B和后向引用會報錯。同樣,在一個ClassAtom中使用后向引用會報錯。

The RegExp Constructor Called as a Function

RegExp(pattern, flags)

 如果pattern是一個對象R,其內部屬性[[Class]]為 RegExp且flags 為undefined,返回R。否則,調用內置RegExp構造器,通過表達式 new RegExp(pattern,flags)返回由該構造器構造的對象。

The RegExp Constructor

 當RegExp作為 new 表達式一部分調用時,它是一個構造器,用來初始化一個新創(chuàng)建的對象。

new RegExp(pattern, flags)

 如果 pattern 是一個對象R,其內部 [[CLASS]] 屬性為RegExp,且 flags 為 undefined,那么,令 P 為 pattern 和令 F 為 flags 用來構造 R。如果pattern是一個對象R,其內部[[CLASS]]屬性為RegExp,且flags為undefined,那么,拋出TypeError異常。否則,如果pattern為undefined且ToString(pattern),令P為空的字符串;如果flags為undefined且ToString(flags)令F為空字符串。

 如果字符P不滿足Pattern語義,那么拋出SyntaxError異常。否則,令新構造的對象擁有內部[[Match]]屬性,該屬性通過執(zhí)行(編譯)字符P作為在15.10.2節(jié)描述的Pattern。

 如果F含有除“g”,“i”,“m”外的任意字符,或者F中包括出現多次的字符,那么,拋出SyntaxError異常。

 如果SyntaxError異常未拋出,那么:

 令S為一個字符串,其等價于P表示的Pattern,S中的字符按如下描述進行轉義。這樣,S可能或者不會與P或者pattern相同;然而,由執(zhí)行S作為一個Pattern的內部處理程序必須和通過構造對象的內部[[Match]]屬性的內部處理程序完全相同。

 如果pattern里存在字符/或者\,那么這些字符應該被轉義,以確保由“/”,S,“/”構成的的字符串的S值有效,而且F能被解析(在適當的詞法上下文中)為一個與構造的正則表達式行為完全相同的 RegularExpressionLiteral 。例如,如果P是“/”,那么S應該為“\/”或“\u002F”,而不是“/”,因為F后的 /// 會被解析為一個 SingleLineComment,而不是一個 RegularExpressionLiteral。 如果P為空字符串,那么該規(guī)范定義為令S為“(?:)”。

 這個新構造對象的如下屬性為數據屬性,其特性在15.10.7中定義。各屬性的[[Value]]值按如下方式設置:

 其source屬性置為S。

 其global屬性置為一個Boolean值。當F含有字符g時,為true,否則,為false。

 其ignoreCase屬性置為一個Boolean值。當F含有字符i時,為true,否則,為false。

 其multiline屬性置為一個Boolean值。當F含有字符m時,為true,否則,為false。

 其lastIndex屬性置為0。

 其內部[[Prototype]]屬性置為15.10.6中定義的內置RegExp原型對象。

 其內部[[Class]]屬性置為“RegExp”。

 如果pattern為 StringLiteral,一般的轉義字符替換發(fā)生在被RegExp處理前。如果pattern必須含有RegExp識別的轉義字符,那么當構成 StringLiteral的內容時,為了防止被移除\被移除,在 StringLiteral中的任何\必須被轉義

Properties of the RegExp Constructor

 RegExp構造器的[[Prototype]]值為內置Function的原型(15.3.4)。

 除了內部的一些屬性和length屬性(其值為2),RegExp構造器還有如下屬性:

RegExp.prototype

 RegExp.prototype的初始值為RegExp的原型(15.10.6)。

 該屬性有這些特性: { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

Properties of the RegExp Prototype Object

 RegExp的原型的內部[[Prototype]]屬性為Object的原型(15.2.4)。RegExp的原型為其本身的一個普通的正則表達式對象;它的[[Class]]為“RegExp”。RegExp的原型對象的數據式屬性的初始值被設置為仿佛由內置RegExp構造器深生成的表達式new RegExp()創(chuàng)建的對象。

 RegExp的原型本身沒有valueOf屬性;然而,該valueOf屬性是繼承至Object的原型。

 在作為RegExp原型對象的屬性的如下函數描述中,“this RegExp object”是指函數激活時this對象;如果this值不是一個對象,或者一個其內部[[Class]]屬性值不是“RegExp”的對象,那么一個TypeError會拋出。

RegExp.prototype.constructor

 RegExp.prototype.constructor 的初始值為內置 RegExp 構造器。

RegExp.prototype.exec(string)

 Performs a regular expression match of string against the regular expression and returns an Array object containing the results of the match, or null if string did not match.

 The String ToString(string) is searched for an occurrence of the regular expression pattern as follows:

  1. 令R為這一RegExp對象.
  2. 令S為ToString(string)的值.
  3. 令length為S的長度.
  4. 令lastIndex為以參數"lastIndex"調用R的內部方法[[Get]]的結果
  5. 令i為ToInteger(lastIndex)的值.
  6. 令global為以參數"global"調用R的內部方法[[Get]]的結果
  7. 若global為false, 則令 i = 0.
  8. 令matchSucceeded為false.
  9. 到matchSucceeded為false前重復以下若i < 0 或者 i > length, 則以參數"lastIndex", 0, and true調用R的內部方法[[Put]]Return null.以參數S 和 i調用R的內部方法[[Match]]若 [[Match]] 返回失敗, 則令 i = i+1.否則令r為調用[[Match]]的結果State.設matchSucceeded為true.
  10. 令e為r的endIndex值.
  11. 若global為true,
  12. 以參數"lastIndex", e, 和true調用R的內部方法[[Put]]
  13. 令n為r的捕獲數組的長度. (這跟15.10.2.1's NCapturingParens是同一個值)
  14. 令A為如同以表達式new Array創(chuàng)建的新數組,其中Array是這個名字的內置構造器.
  15. 令matchIndex為匹配到的子串在整個字符串S中的位置。
  16. 以參數"index", 屬性描述{[[Value]]: matchIndex, [[Writable]: true, [[Enumerable]]: true, [[Configurable]]: true}, 和true調用A的內部方法[[DefineOwnProperty]]
  17. 以參數"input", 屬性描述{[[Value]]: S, [[Writable]: true, #[[Enumerable]]: true, [[Configurable]]: true}, 和true調用A的內部方法[[DefineOwnProperty]]
  18. 以參數"length", 屬性描述{[[Value]]: n + 1}, 和true調用A的內部方法[[DefineOwnProperty]]
  19. 令matchedSubstr為匹配到的子串(i.e. the portion of S between offset i inclusive and offset e exclusive).
  20. 以參數"0", 屬性描述{[[Value]]: matchedSubstr, [[Writable]: true, [[Enumerable]]: true, [[Configurable]]: true}, 和true調用A的內部方法[[DefineOwnProperty]]
  21. 對每一滿足I > 0且I ≤ n的整數i令captureI為第i個捕獲數組中的元素.以參數ToString(i), 屬性描述{[[Value]]: captureI, [[Writable]: true, [[Enumerable]]: true, [[Configurable]]: true}, 和true調用A的內部方法[[DefineOwnProperty]]
  22. 返回 A.

RegExp.prototype.test(string)

 采用如下步驟:

  1. 令match為在這個RegExp對象上使用string作為參數執(zhí)行 RegExp.prototype.exec (15.10.6.2) 的結果。
  2. 如果match不為null,返回true;否則返回false。

RegExp.prototype.toString()

 返回一個String,由“/”,RegExp對象的source屬性值,“/”與“g”(如果global屬性為true),“i”(如果ignoreCase為true),“m”(如果multiline為true)通過連接組成。

 如果返回的字符串包含一個RegularExpressionLiteral,那么該RegularExpressionLiteral用同樣的方式解釋執(zhí)行。

Properties of RegExp Instances

 RegExp實例繼承至RegExp原型對象,其[[CLASS]]內部屬性值為“RegExp”。RegExp實例也擁有一個[[Match]]內部屬性和一個length屬性。

 內部屬性[[Match]]的值是正則表達式對象的Pattern的依賴實現的表示形式。

 RegExp實例還有如下屬性。

source

 source屬性為構成正則表達式Pattern的字符串。該屬性擁有這些特性{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

global

 global屬性是一Boolean值,表示正則表達式flags是否有“g”。該屬性擁有這些特性{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

ignoreCase

 ignoreCase屬性是一Boolean值,表示正則表達式flags是否有“i”。該屬性擁有這些特性{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

multiline

 multiline屬性是一Boolean值,表示正則表達式flags是否有“m”。該屬性擁有這些特性{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

lastIndex

 lastIndex屬性指定從何處開始下次匹配的一個字符串類型的位置索引。當需要時該值會轉換為一個整型數。該屬性擁有這些特性{ [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

 不同于其他RegExp實例內置屬性,lastIndex是可寫的。


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號