diff --git a/docs/regex.md b/docs/regex.md index 28beaa1..1103f41 100644 --- a/docs/regex.md +++ b/docs/regex.md @@ -350,7 +350,7 @@ escape('hi. how are you?') JavaScript语言的正则表达式,只支持先行断言(lookahead)和先行否定断言(negative lookahead),不支持后行断言(lookbehind)和后行否定断言(negative lookbehind)。 -目前,有一个提案,在ES7加入后行断言。V8引擎4.9版已经支持,Chrome浏览器49版打开”experimental JavaScript features“开关(地址栏键入`about:flags`),就可以使用这项功能。 +目前,有一个[提案](https://github.com/goyakin/es-regexp-lookbehind),在ES7加入后行断言。V8引擎4.9版已经支持,Chrome浏览器49版打开”experimental JavaScript features“开关(地址栏键入`about:flags`),就可以使用这项功能。 ”先行断言“指的是,`x`只有在`y`前面才匹配,必须写成`/x(?=y)/`。比如,只匹配百分号之前的数字,要写成`/\d+(?=%)/`。”先行否定断言“指的是,`x`只有不在`y`前面才匹配,必须写成`x(?!y)`。比如,只匹配不在百分号之前的数字,要写成`/\d+(?!%)/`。 @@ -370,20 +370,22 @@ JavaScript语言的正则表达式,只支持先行断言(lookahead)和先 上面的例子中,正则表达式的括号之中的部分,也是不计入返回结果。 -但是,如果括号之中还有括号,就会当作组匹配,返回匹配结果。 +”后行断言“的实现,需要先匹配`/(?<=y)x/`的`x`,然后再回到左边,匹配`y`的部分。这种”先右后左“的执行顺序,与所有其他正则操作相反,导致了一些不符合预期的行为。 + +首先,”后行断言“的组匹配,与正常情况下结果是不一样的。 ```javascript -/h(?=(\w)+)/.exec("hodor") // ["h", "r"] -/(?<=(\w)+)r/.exec("hodor") // ["r", "h"] +/(?<=(\d+)(\d+))$/.exec('1053') // ["", "1", "053"] +/^(\d+)(\d+)$/.exec('1053') // ["1053", "105", "3"] ``` -上面代码中,第一个正则表达式是”先行断言“,只匹配后面跟着一个多个任意字符(`\w`)的`h`,这时符合条件的右边最后一个字符,会被括号之中的那个括号捕获返回,上例是`r`。第二个正则表达式是”后行断言“,只匹配前面是一个或多个任意字符(`\w`)的`r`,这时符合条件的左边第一个字符,会被括号之中的那个括号捕获返回,上例是`h`。 +上面代码中,需要捕捉两个组匹配。没有”后行断言“时,第一个括号是贪婪模式,第二个括号只能捕获一个字符,所以结果是`105`和`3`。而”后行断言“时,由于执行顺序是从右到左,第二个括号是贪婪模式,第一个括号只能捕获一个字符,所以结果是`1`和`053`。 -括号之中的那个括号捕获的部分,还可以用反斜杠引用。但是,”后行断言“的反斜杠引用,与通常的顺序相反,必须在对应的那个括号之前。 +其次,”后行断言“的反斜杠引用,也与通常的顺序相反,必须放在对应的那个括号之前。 ```javascript /(?<=(o)d\1)r/.exec("hodor") // null /(?<=\1d(o))r/.exec("hodor") // ["r", "o"] ``` -上面代码中,如果反斜杠引用(`\1`)在括号的后面,就不会得到匹配结果,必须放在前面才可以。 +上面代码中,如果后行断言的反斜杠引用(`\1`)放在括号的后面,就不会得到匹配结果,必须放在前面才可以。