Skip to content

Commit 6097cc3

Browse files
committed
docs(regex): edit regex
1 parent ee982c4 commit 6097cc3

File tree

3 files changed

+74
-10
lines changed

3 files changed

+74
-10
lines changed

docs/reference.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
- Axel Rauschmayer, [New regular expression features in ECMAScript 6](http://www.2ality.com/2015/07/regexp-es6.html):ES6 正则特性的详细介绍
6868
- Yang Guo, [RegExp lookbehind assertions](http://v8project.blogspot.jp/2016/02/regexp-lookbehind-assertions.html):介绍后行断言
6969
- Axel Rauschmayer, [ES proposal: RegExp named capture groups](http://2ality.com/2017/05/regexp-named-capture-groups.html): 具名组匹配的介绍
70+
- Mathias Bynens, [ECMAScript regular expressions are getting better!](https://mathiasbynens.be/notes/es-regexp-proposals): 介绍 ES2018 添加的多项正则语法
7071

7172
## 数值
7273

docs/regex.md

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -291,9 +291,9 @@ ES6 为正则表达式新增了`flags`属性,会返回正则表达式的修饰
291291

292292
## s 修饰符:dotAll 模式
293293

294-
正则表达式中,点(`.`)是一个特殊字符,代表任意的单个字符,但是行终止符(line terminator character)除外
294+
正则表达式中,点(`.`)是一个特殊字符,代表任意的单个字符,但是有两个例外。一个是四个字节的 UTF-16 字符,这个可以用`u`修饰符解决;另一个是行终止符(line terminator character)。
295295

296-
以下四个字符属于”行终止符“。
296+
所谓行终止符,就是该字符表示一行的终结。以下四个字符属于”行终止符“。
297297

298298
- U+000A 换行符(`\n`
299299
- U+000D 回车符(`\r`
@@ -314,7 +314,7 @@ ES6 为正则表达式新增了`flags`属性,会返回正则表达式的修饰
314314
// true
315315
```
316316

317-
这种解决方案毕竟不太符合直觉,所以现在有一个[提案](https://github.com/mathiasbynens/es-regexp-dotall-flag),引入`/s`修饰符,使得`.`可以匹配任意单个字符。
317+
这种解决方案毕竟不太符合直觉,ES2018 [引入](https://github.com/tc39/proposal-regexp-dotall-flag)`s`修饰符,使得`.`可以匹配任意单个字符。
318318

319319
```javascript
320320
/foo.bar/s.test('foo\nbar') // true
@@ -336,7 +336,7 @@ re.flags // 's'
336336

337337
## 后行断言
338338

339-
JavaScript 语言的正则表达式,只支持先行断言(lookahead)和先行否定断言(negative lookahead),不支持后行断言(lookbehind)和后行否定断言(negative lookbehind)。目前,有一个[提案](https://github.com/goyakin/es-regexp-lookbehind)引入后行断言,V8 引擎 4.9 版已经支持
339+
JavaScript 语言的正则表达式,只支持先行断言(lookahead)和先行否定断言(negative lookahead),不支持后行断言(lookbehind)和后行否定断言(negative lookbehind)。ES2018 引入[后行断言](https://github.com/tc39/proposal-regexp-lookbehind),V8 引擎 4.9 版(Chrome 62)已经支持
340340

341341
”先行断言“指的是,`x`只有在`y`前面才匹配,必须写成`/x(?=y)/`。比如,只匹配百分号之前的数字,要写成`/\d+(?=%)/`。”先行否定断言“指的是,`x`只有不在`y`前面才匹配,必须写成`/x(?!y)/`。比如,只匹配不在百分号之前的数字,要写成`/\d+(?!%)/`
342342

@@ -375,9 +375,9 @@ const RE_DOLLAR_PREFIX = /(?<=\$)foo/g;
375375
/^(\d+)(\d+)$/.exec('1053') // ["1053", "105", "3"]
376376
```
377377

378-
上面代码中,需要捕捉两个组匹配。没有"后行断言"时,第一个括号是贪婪模式,第二个括号只能捕获一个字符,所以结果是`105``3`。而"后行断言"时,由于执行顺序是从右到左,第二个括号是贪婪模式,第一个括号只能捕获一个字符,所以结果是`1``053`
378+
上面代码中,需要捕捉两个组匹配。没有后行断言时,第一个括号是贪婪模式,第二个括号只能捕获一个字符,所以结果是`105``3`。而后行断言时,由于执行顺序是从右到左,第二个括号是贪婪模式,第一个括号只能捕获一个字符,所以结果是`1``053`
379379

380-
其次,"后行断言"的反斜杠引用,也与通常的顺序相反,必须放在对应的那个括号之前。
380+
其次,后行断言的反斜杠引用,也与通常的顺序相反,必须放在对应的那个括号之前。
381381

382382
```javascript
383383
/(?<=(o)d\1)r/.exec('hodor') // null
@@ -388,7 +388,7 @@ const RE_DOLLAR_PREFIX = /(?<=\$)foo/g;
388388

389389
## Unicode 属性类
390390

391-
目前,有一个[提案](https://github.com/mathiasbynens/es-regexp-unicode-property-escapes),引入了一种新的类的写法`\p{...}``\P{...}`,允许正则表达式匹配符合 Unicode 某种属性的所有字符。
391+
ES2018 [引入](https://github.com/tc39/proposal-regexp-unicode-property-escapes)了一种新的类的写法`\p{...}``\P{...}`,允许正则表达式匹配符合 Unicode 某种属性的所有字符。
392392

393393
```javascript
394394
const regexGreekSymbol = /\p{Script=Greek}/u;
@@ -403,10 +403,11 @@ Unicode 属性类要指定属性名和属性值。
403403
\p{UnicodePropertyName=UnicodePropertyValue}
404404
```
405405

406-
对于某些属性,可以只写属性名。
406+
对于某些属性,可以只写属性名,或者只写属性值
407407

408408
```javascript
409409
\p{UnicodePropertyName}
410+
\p{UnicodePropertyValue}
410411
```
411412

412413
`\P{…}``\p{…}`的反向匹配,即匹配不满足条件的字符。
@@ -435,12 +436,18 @@ regex.test('ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ') // true
435436
下面是其他一些例子。
436437

437438
```javascript
439+
// 匹配所有空格
440+
\p{White_Space}
441+
438442
// 匹配各种文字的所有字母,等同于 Unicode 版的 \w
439443
[\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]
440444

441445
// 匹配各种文字的所有非字母的字符,等同于 Unicode 版的 \W
442446
[^\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]
443447

448+
// 匹配 Emoji
449+
/\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F/gu
450+
444451
// 匹配所有的箭头字符
445452
const regexArrows = /^\p{Block=Arrows}+$/u;
446453
regexArrows.test('←↑→↓↔↕↖↗↘↙⇏⇐⇑⇒⇓⇔⇕⇖⇗⇘⇙⇧⇩') // true
@@ -459,15 +466,17 @@ const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/;
459466
上面代码中,正则表达式里面有三组圆括号。使用`exec`方法,就可以将这三组匹配结果提取出来。
460467

461468
```javascript
469+
const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/;
470+
462471
const matchObj = RE_DATE.exec('1999-12-31');
463472
const year = matchObj[1]; // 1999
464473
const month = matchObj[2]; // 12
465474
const day = matchObj[3]; // 31
466475
```
467476

468-
组匹配的一个问题是,每一组的匹配含义不容易看出来,而且只能用数字序号引用,要是组的顺序变了,引用的时候就必须修改序号。
477+
组匹配的一个问题是,每一组的匹配含义不容易看出来,而且只能用数字序号(比如`matchObj[1]`)引用,要是组的顺序变了,引用的时候就必须修改序号。
469478

470-
现在有一个“具名组匹配”(Named Capture Groups)的[提案](https://github.com/tc39/proposal-regexp-named-groups),允许为每一个组匹配指定一个名字,既便于阅读代码,又便于引用。
479+
ES2018 引入了[具名组匹配](https://github.com/tc39/proposal-regexp-named-groups)(Named Capture Groups),允许为每一个组匹配指定一个名字,既便于阅读代码,又便于引用。
471480

472481
```javascript
473482
const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
@@ -559,3 +568,53 @@ const RE_TWICE = /^(?<word>[a-z]+)!\k<word>!\1$/;
559568
RE_TWICE.test('abc!abc!abc') // true
560569
RE_TWICE.test('abc!abc!ab') // false
561570
```
571+
572+
## String.prototype.matchAll
573+
574+
如果一个正则表达式在字符串里面有多个匹配,现在一般使用`g`修饰符或`y`修饰符,在循环里面逐一取出。
575+
576+
```javascript
577+
var regex = /t(e)(st(\d?))/g;
578+
var string = 'test1test2test3';
579+
580+
var matches = [];
581+
var match;
582+
while (match = regex.exec(string)) {
583+
matches.push(match);
584+
}
585+
586+
matches
587+
// [
588+
// ["test1", "e", "st1", "1", index: 0, input: "test1test2test3"],
589+
// ["test2", "e", "st2", "2", index: 5, input: "test1test2test3"],
590+
// ["test3", "e", "st3", "3", index: 10, input: "test1test2test3"]
591+
// ]
592+
```
593+
594+
上面代码中,`while`循环取出每一轮的正则匹配,一共三轮。
595+
596+
目前有一个[提案](https://github.com/tc39/proposal-string-matchall),增加了`String.prototype.matchAll`方法,可以一次性取出所有匹配。不过,它返回的是一个遍历器(Iterator),而不是数组。
597+
598+
```javascript
599+
const string = 'test1test2test3';
600+
const regex = /t(e)(st(\d?))/g;
601+
for (const match of string.matchAll(regex)) {
602+
console.log(match);
603+
}
604+
// ["test1", "e", "st1", "1", index: 0, input: "test1test2test3"]
605+
// ["test2", "e", "st2", "2", index: 5, input: "test1test2test3"]
606+
// ["test3", "e", "st3", "3", index: 10, input: "test1test2test3"]
607+
```
608+
609+
上面代码中,由于`string.matchAll(regex)`返回的是遍历器,所以可以用`for...of`循环取出。相对于返回数组,返回遍历器的好处在于,如果匹配结果是一个很大的数组,那么遍历器比较节省资源。
610+
611+
遍历器转为数组是非常简单的,使用`...`运算符和`Array.from`方法就可以了。
612+
613+
```javascript
614+
// 转为数组方法一
615+
[...string.matchAll(regex)]
616+
617+
// 转为数组方法二
618+
Array.from(string.matchAll(regex));
619+
```
620+

docs/string.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,10 @@ ES2017 引入了字符串补全长度的功能。如果某个字符串不够指
349349
'09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12"
350350
```
351351

352+
## matchAll()
353+
354+
`matchAll`方法返回一个正则表达式在当前字符串的所有匹配,详见《正则的扩展》的一章。
355+
352356
## 模板字符串
353357

354358
传统的 JavaScript 语言,输出模板通常是这样写的。

0 commit comments

Comments
 (0)