RegExp ( 正则表达式 ) 对象

2018-06-16 15:48 更新

 一个 RegExp 对象包含一个正则表达式和关联的标志。

 正则表达式的格式和功能是以 Perl 5 程序语言的正则表达式设施为蓝本的。

模式

 RegExp 构造器对输入模式字符串应用以下文法。如果文法无法将字符串解释为 Pattern 的一个展开形式,则发生错误。

 语法:

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 用来表示正则表达式匹配算法里的局部匹配状态。endIndex 是到目前为止模式匹配的最后一个输入字符的索引值加上一,而 captures 持有捕获括号的捕获结果。captures 的第 n 个元素是一个代表第 n 个捕获括号对捕获值的字符串,或如果第 n 个捕获括号对未能达到目的,captures 的第 n 个元素是 undefined。由于回溯,很多 States 可能在匹配过程中的任何时候被使用。
  • MatchResult,值为 State 或表示匹配失败特殊 token--failure。
  • Continuation 程序,是一个内部闭包(即,一些参数已经绑定了值的内部程序),它用一个 State 参数返回一个 MatchResult 结果。 如果一个内部闭包引用的变量是绑定在创建这个闭包的函数里 , 则闭包使用在创建闭包时的这些变量值。Continuation 尝试从其 State 参数给定的中间状态开始用模式的其余部分(由闭包的已绑定参数指定)匹配输入字符串。如果匹配成功,Continuation 返回最终的 State;如果匹配失败,Continuation 返回 failure。
  • Matcher 程序,是一个需要两个参数 -- 一个 State 和一个 Continuation -- 的内部闭包,它返回一个 MatchResult 结果。 Matcher 尝试从其 State 参数给定的中间状态开始用模式的一个中间子模式(由闭包的已绑定参数指定)匹配输入字符串。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 按照以下方式解释执行 :

  1. 解释执行 Disjunction ,获得一个 Matcher m.
  2. 返回一个需要两个参数的内部闭包,一个字符串 str 和一个整数 index, 执行方式如下 :令 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),并返回结果 .

 一个模式解释执行(“编译”)为一个内部程序值。RegExp.prototype.exec 可将这个内部程序应用于一个字符串和字符串的一个偏移位,来确定从这个偏移位开始 , 模式是否能够匹配,如果能匹配,将返回捕获括号的值。15.10.2 中的算法被设计为只在编译一个模式时可抛出一个 SyntaxError 异常;反过来说,一旦模式编译成功,应用编译生成的内部程序在字符串中寻找匹配结果时不可抛出异常(除非是宿主定义的可在任何时候出现的异常,如内存不足)。

析取(Disjunction)

 产生式 Disjunction :: Alternative 的解释执行,是解释执行 Alternative 来获得 Matcher 并返回这个 Matcher。

 产生式 Disjunction :: Alternative | Disjunction 按照以下方式解释执行:

  1. 解释执行 Alternative 来获得一个 Matcher m1.
  2. 解释执行 Disjunction 来获得一个 Matcher m2.
  3. 返回一个需要两个参数的内部闭包 Matcher ,参数分别是一个 State x 和一个 Continuation c,此内部闭包的执行方式如下:调用 m1(x, c) 并令 r 为其结果。如果 r 不是 failure, 返回 r.调用 m2(x, c) 并返回其结果。

 正则表达式运算符 | 用来分隔两个选择项。模式首先尝试去匹配左侧的 Alternative( 紧跟着是正则表达式的后续匹配结果 );如果失败,尝试匹配右侧的 Disjunction(紧跟着是正则表达式的后续匹配结果)。如果左侧的 Alternative,右侧的 Disjunction,还有后续匹配结果,全都有可选的匹配位置,则后续匹配结果的所有可选位置是在左侧的 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] 解释执行返回一个 Matcher,它需要两个参数,一个 State x 和 一个 Continuation c,并返回调用 c(x) 的结果。

 产生式 Alternative :: Alternative Term 按照如下方式解释执行:

  1. 解释执行 Alternative 来获得一个 Matcher m1.
  2. 解释执行 Term 来获得一个 Matcher m2.
  3. 返回一个内部闭包 Matcher,它需要两个参数,一个 State x 和一个 Continuation c, 执行方式如下 :创建一个 Continuation d ,它需要一个 State 参数 y ,返回调用 m2(y, c) 的结果 .调用 m1(x, d) 并返回结果 .

 连续的 Term 试着同时去匹配连续输入字符串的连续部分。如果左侧的 Alternative,右侧的 Term,还有后续匹配结果,全都有可选的匹配位置,则后续匹配结果的所有可选位置是在右侧的 Term 移动到下一个可选位置之前确定的,并且则右侧的 Term 的所有可选位置是在左侧的 Alternative 移动到下一个可选位置之前确定的。

匹配项(Term)

 产生式 Term :: Assertion 解释执行,返回一个需要两个参数 State x 和 Continuation c 的内部闭包 Matcher,它的执行方式如下:

  1. 解释执行 Assertion 来获得一个 AssertionTester t.
  2. 调用 t(x) 并令 r 为调用结果布尔值 .
  3. 如果 r 是 false, 返回 failure.
  4. 调用 c(x) 并返回结果 .

 产生式 Term :: Atom 的解释执行方式是,解释执行 Atom 来获得一个 Matcher 并返回这个 Matcher。

 产生式 Term :: Atom Quantifier 的解释执行方式如下 :

  1. 解释执行 Atom 来获得一个 Matcher m.
  2. 解释执行 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,执行方式如下 :调用 RepeatMatcher(m, min, max, greedy, x, c, parenIndex, parenCount) ,并返回结果 .

 抽象操作 RepeatMatcher 需要八个参数,一个 Matcher m, 一个整数 min, 一个整数 ( 或 ∞) max, 一个布尔值 greedy, 一个 State x, 一个 Continuation c, 一个整数 parenIndex, 一个整数 parenCount, 执行方式如下 :

  1. 如果 max 是零 , 则调用 c(x) ,并返回结果 .
  2. 创建需要一个 State 参数 y 的内部 Continuation 闭包 d ,执行方式如下 :如果 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和后续的正则表达式都有选择余地,Atom首先尽量多匹配(或者尽量少,假如是非贪婪模式)在最后一次Atom的重复中移动到下一个选择前,所有的后续中的选项<都应该被尝试。 在倒数第二次(第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闭包状态步骤1,一旦重复的最小次数达到,任何Atom匹配空String的扩展不再会匹配到重复中。这可以避免正则引擎在匹配类似下面的模式时掉进无限循环:

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

 或者稍微复杂一点:

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

 它返回数组:

["b", ""]

Assertion

 产生式Assertion :: ^ 解释执行返回一个 AssertionTester , 它需要1个参数 State x,并按如下算法执行:

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

 产生式Assertion :: $ 解释执行返回一个 AssertionTester , 它需要1个参数 State x,并按如下算法执行:

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

 产生式Assertion :: \ b 解释执行返回一个 AssertionTester , 它需要1个参数 State x,并按如下算法执行:

  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 解释执行返回一个 AssertionTester , 它需要1个参数 State x,并按如下算法执行:

  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) 按如下算法执行:

  1. 执行Disjunction ,得到 Matcher m
  2. 返回一个需要两个参数的内部闭包 Matcher ,参数分别是一个 State x 和一个 Continuation c,此内部闭包的执行方式如下::使 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) 按如下算法执行:

  1. 执行Disjunction ,得到 Matcher m
  2. 返回一个需要两个参数的内部闭包 Matcher ,参数分别是一个 State x 和一个 Continuation c,此内部闭包的执行方式如下::使 d 为一个Continuation,它始终对它的任何 State 参数都返回成功匹配的 MatchResult调用m(x, d),令r为其结果若r为failure,返回 failure调用c(z),返回结果

 抽象操作 IsWordChar ,拥有一个integer类型的参数e,按如下方式执行:

  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 按如下方式执行:

  1. 执行 QuantifierPrefix 得到 2个数 min 和 max(或 ∞)
  2. 返回 min,max,true

 产生式 Quantifier :: QuantifierPrefix ? 按如下方式执行:

  1. 执行 QuantifierPrefix 得到 2个数 min 和 max(或 ∞)
  2. 返回 min,max,true

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

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

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

 产生式 Quantifier :: { DecimalDigits } 按如下方式执行:

  1. 令 i 为 DecimalDigits 的 MV
  2. 返回2个结果 i,i

 产生式 Quantifier :: { DecimalDigits, } 按如下方式执行:

  1. 令 i 为 DecimalDigits 的 MV
  2. 返回2个结果 i,∞

 产生式 Quantifier :: { DecimalDigits, DecimalDigits} 按如下方式执行:

  1. 令 i 为 DecimalDigits 的 MV
  2. 令 j 为 DecimalDigits 的 MV
  3. 返回2个结果 i,j

Atom

 产生式 Atom :: PatternCharacter 执行方式如下:

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

 产生式 Atom :: . 执行方式如下:

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

 产生式 Atom :: \ AtomEscape 通过执行 AtomEscape 返回 Matcher。

 产生式 Atom :: CharacterClass 执行方式如下:

  1. 执行 CharacterClass 得到 CharSet A 和 Boolean invert
  2. 调用 CharacterSetMatcher(A, false),返回Matcher

 产生式 Atom :: ( Disjunction ) 执行方式如下:

  1. 执行 Disjunction 得到 Matcher
  2. 令 parenIndex 为 在整个正则表达式中从产生式展开初始化左括号时,当前展开左捕获括号的索引。parenIndex 为在产生式的 Atom 被展开之前,Atom :: ( Disjunction )产生式被展开的次数,加上Atom :: ( Disjunction ) 闭合 这个Atom的次数
  3. 返回一个内部闭包 Matcher,拥有2个参数:一个 State x 和 Continuation c,执行方式如下:创建内容闭包 Continuation d,参数为State y,并按如下方式执行:令cap为y的capture数组的一个拷贝令xe为x的endIndex令ye为y的endIndex令s为Input从索引xe(包括)至 ye(不包括)范围的新创建的字符串令s为cap[parenIndex+1]令z为 State (ye, cap)调用c(z),返回其结果执行m(x, d),返回其结果

 产生式 Atom :: ( ? : Disjunction ) 通过执行Disjunction 得到并返回一个Matcher。

 抽象操作 CharacterSetMatcher ,拥有2个参数:一个 CharSet A 和 Boolean invert标志,按如下方式执行:

  1. 返回一个内部闭包 Matcher,拥有2个参数:一个 State x 和 Continuation c,执行方式如下:令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,按如下方式执行:

  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 必须首先能够匹配成功,但在匹配后续字符前,其当前位置会不变。如果 Disjunction 能在当前位置以多种方式匹配,那么只会取第一次匹配的结果。不像其他正则表达式运算符,(?= 内部不会回溯(这个特殊的行为是从Perl继承过来的)。在 Disjunction 含有捕获括号,模式的后续字符包括后向引用时匹配结果会有影响。

 例如,

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

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

["", "aaa"]

 为了说明预查不会回溯,

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

 得到:

["aba", "a"]

 而不是:

["aaaba", "a"]

 (?! Disjunction ) 指定一个零宽正向否定预查。为了保证匹配成功,其 Disjunction 必须首先能够匹配失败,但在匹配后续字符前,其当前位置会不变。Disjunction 能含有捕获括号,但是对这些捕获分组的后向引用只在Disjunction中有效。在当前模式的其他位置后向引用捕获分组都会返回undefined。因为否定预查必须满足预查失败来保证模式成功匹配。例如,

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

 搜索a,其后有n个a,一个b,n个a(\2指定)和一个c。第二个\2位于负向预查模式的外部,因此它匹配undefined,且总是成功的。整个表达式返回一个数组:

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

 在发生比较前,一次不区分大小写的匹配中所有的字符都会隐式转换为大写。然而,如果某些单个字符在转换为大写时扩展为多个字符,那么该字符会保持原样。当某些非ASCII字符在转换为大写时变成ASCII字符,该字符也会保持原样。这样会阻止Unicode字符(例如\u0131和\u017F)匹配正则表达式 (例如仅匹配ASCII字符的正则表达式/[a z]/i)。而且,如果转换允许,/[^\W]/i会匹配除去i或s外的每一个a,b,......,h。

AtomEscape

 产生式 AtomEscape :: DecimalEscape 执行方式如下:

  1. 执行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,执行方式如下:令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 执行方式如下:

  1. 执行CharacterEscape 得到一个ch字符
  2. 令A为包含ch字符的单元素字符集CharSet
  3. 调用 CharacterSetMatcher(A, false) 返回Matcher结果

 产生式 AtomEscape :: CharacterClassEscape 执行方式如下:

  1. 执行CharacterClassEscape 得到一个CharSet A
  2. 调用 CharacterSetMatcher(A, false) 返回Matcher结果

 格式\后为非零数n的转义序列匹配捕获分组的第n次匹配结果。如果正则表达式少于n个捕获括号,会报错。如果正则表达式大于等于n个捕获括号,由于没有捕获到任何东西,导致第n个捕获分组结果为undefined,那么后向引用总是成功的。

CharacterEscape

 产生式 CharacterEscape :: ControlEscape 执行返回一个根据表23定义的字符:

ControlEscape字符转义值
ControlEscape字符编码值名称符号
t\u0009水平制表符<HT>
n\u000A进行(新行)<LF>
v\u000B竖直制表符<VT>
f\u000C进纸<FF>
r\u000D回车<CR>

 产生式 CharacterEscape :: ch ControlLetter 执行过程如下:

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

 产生式 CharacterEscape :: HexEscapeSequence 执行HexEscapeSequence的CV,返回其字符结果。

 产生式 CharacterEscape :: UnicodeEscapeSequence 执行UnicodeEscapeSequence的CV,返回其字符结果。

 产生式 CharacterEscape :: IdentityEscape执行返回由IdentityEscape表示的字符。

DecimalEscape

 产生式 DecimalEscape :: DecimalIntegerLiteral [lookahead ∉ DecimalDigit] 按如下方式执行:

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

 “the MV of DecimalIntegerLiteral”在7.8.3节定义。

 如果\后面是一个数字,且首位为0,那么,该转义序列被认为是一个后向引用。如果n比在整个正则表达式左捕获括号个数大,那么会出错。\0 表示 <NUL>字符,其后不能再有数字。

CharacterClassEscape

 产生式 CharacterClassEscape :: d执行返回包含0到9之间的十元素字符集。

 产生式 CharacterClassEscape :: D执行返回不包括 CharacterClassEscape :: d的字符集。

 产生式 CharacterClassEscape :: s执行返回包含 WhiteSpace 或 LineTerminator 产生式右部分字符的字符集。

 产生式 CharacterClassEscape :: S执行返回不包括 CharacterClassEscape :: s的字符集。

 产生式 CharacterClassEscape :: w执行返回包含如下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执行返回不包括CharacterClassEscape :: w的字符集。

CharacterClass

 产生式 CharacterClass :: [ [lookahead ∉ {^}] ClassRanges ] 通过执行ClassRanges获得并返回这个CharSet和Boolean false。

 产生式 CharacterClass :: [ ^ ClassRanges ] 通过执行ClassRanges获得并返回这个CharSet和Boolean true。

ClassRanges

 产生式 ClassRanges :: [empty]执行返回一个空的CharSet。

 产生式 ClassRanges :: NonemptyClassRanges 通过执行 NonemptyClassRanges 获得并返回这个CharSet。

NonemptyClassRanges

 产生式 NonemptyClassRanges :: ClassAtom 通过执行ClassAtom获得一个CharSet并返回这个CharSet。

 产生式 NonemptyClassRanges :: ClassAtom NonemptyClassRangesNoDash 按如下方式执行:

  1. 执行 ClassAtom 得到一个CharSet A
  2. 执行 NonemptyClassRangesNoDash 得到一个CharSet B
  3. 返回A与B的并集

 产生式 NonemptyClassRanges :: ClassAtom - ClassAtom ClassRanges 按如下方式执行:

  1. 执行第一个ClassAtom 得到一个CharSet A
  2. 执行第二个ClassAtom 得到一个CharSet B
  3. 执行ClassRanges 得到一个CharSet C
  4. 调用 CharacterRange(A, B),令D为其结果CharSet
  5. 返回D与C的并集

 抽象操作 CharacterRange,拥有2个CharSet参数A和B,执行方式如下:

  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 执行过程是执行ClassAtom产生一个CharSet并且返回这个CharSet。

 产生式NonemptyClassRangesNoDash :: ClassAtomNoDash NonemptyClassRangesNoDash 按以下方式执行:

  1. 执行ClassAtomNoDash产生CharSet A
  2. 执行NonemptyClassRangesNoDash产生CharSet B
  3. 返回CharSet A和B的并集

 产生式NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassRanges 按以下方式执行:

  1. 执行ClassAtomNoDash产生CharSet A
  2. 执行ClassAtom产生CharSet B
  3. 执行ClassRanges产生CharSet C
  4. 调用CharacterRange(A, B)并设CharSet D为结果。
  5. 返回CharSet D和C的并集

 ClassRanges可以拆分成单独的ClassAtom且/或两个用减号分隔的ClassAtom。在后面的情况下ClassAtom包含第一个到第二个ClassAtom间的所有字符。 如果两个ClassAtom之一不是表示一个单独字符(例如其中一个是\w)或者第一个ClassAtom的字符编码值比第二个ClassAtom的字符编码值大则发生错误。

 即使匹配忽略大小写,区间两端的大小写在区分哪些字符属于区间时仍然有效。这意味着,例如模式/[E-F]/仅仅匹配E, F, e, 和 f。/[E-f]/i则匹配所有大写和小写的ASCII字母以及[, \, ], ^, _, 和 `

 -字符可能被当做字面意思或者表示一个区间,它作为ClassRange的开头或者结尾、在区间指定开头或者结尾,或者紧跟一个区间指定的时候被当做字面意思。

ClassAtom

 产生式 ClassAtom :: - 执行返回包含单个字符 - 的字符集。

 产生式 ClassAtom :: ClassAtomNoDash 通过执行 ClassAtomNoDash 获得并返回这个 CharSet。

ClassAtomNoDash

 产生式 ClassAtomNoDash :: SourceCharacter 不包括\,],- 执行返回包含由 SourceCharacter 表示的字符的单元素字符集。

 产生式 ClassAtomNoDash :: \ ClassEscape 通过执行ClassEscape 得到并返回这个CharSet。

ClassEscape

 产生式 ClassEscape :: DecimalEscape 按如下方式执行:

  1. 执行 DecimalEscape 得到 EscapeValue E
  2. 如果E不是一个字符,抛出 SyntaxError异常
  3. 令ch为E的字符
  4. 返回包含字符ch的单元素CharSet

 产生式 ClassEscape :: b 执行返回包含一个<BS>字符(Unicode值0008)的字符集。

 产生式 ClassEscape :: CharacterEscape 通过执行 CharacterEscape 获得一个字符Charset并返回包含该字符的单元素字符集CharSet。

 产生式 ClassEscape :: CharacterClassEscape 通过执行 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 表达式一部分调用时,它是一个构造器,用来初始化一个新创建的对象。

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]]属性,该属性通过执行(编译)字符P作为在15.10.2节描述的Pattern。

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

 如果SyntaxError异常未抛出,那么:

 令S为一个字符串,其等价于P表示的Pattern,S中的字符按如下描述进行转义。这样,S可能或者不会与P或者pattern相同;然而,由执行S作为一个Pattern的内部处理程序必须和通过构造对象的内部[[Match]]属性的内部处理程序完全相同。

 如果pattern里存在字符/或者\,那么这些字符应该被转义,以确保由“/”,S,“/”构成的的字符串的S值有效,而且F能被解析(在适当的词法上下文中)为一个与构造的正则表达式行为完全相同的 RegularExpressionLiteral 。例如,如果P是“/”,那么S应该为“\/”或“\u002F”,而不是“/”,因为F后的 /// 会被解析为一个 SingleLineComment,而不是一个 RegularExpressionLiteral。 如果P为空字符串,那么该规范定义为令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,一般的转义字符替换发生在被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()创建的对象。

 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创建的新数组,其中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作为参数执行 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用同样的方式解释执行。

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

公众号
微信公众号

编程狮公众号