Skip to content

Commit 39bb1de

Browse files
committed
feat: update translation
1 parent e641b4a commit 39bb1de

File tree

1 file changed

+77
-59
lines changed

1 file changed

+77
-59
lines changed

9-regular-expressions/17-regexp-methods/article.md

Lines changed: 77 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
# 正则表达式(RegExp)和字符串(String)的方法
1+
# 正则表达式和字符串的方法
22

3-
在本文中,我们将深入探讨与正则表达式配合使用的各种方法
3+
在本文中,我们将深入介绍与正则表达式配合使用的各种方法
44

55
## str.match(regexp)
66

7-
`str.match(regexp)` 方法在字符串 `str` 中找到匹配 `regexp` 的字符
7+
`str.match(regexp)` 方法在字符串 `str` 中查找 `regexp` 的匹配项
88

99
它有 3 种模式:
1010

11-
1. 如果 `regexp` 不带有 `pattern:g` 标记,则它以数组的形式返回第一个匹配项,其中包含分组和属性 `index`(匹配项的位置)、`input`(输入字符串,等于 `str `):
11+
1. 如果 `regexp` 不带有修饰符 `pattern:g`,则它以数组的形式返回第一个匹配项,其中包含捕获组和属性 `index`(匹配项的位置)、`input`(输入字符串,等于 `str `):
1212

1313
```js run
1414
let str = "I love JavaScript";
@@ -24,7 +24,7 @@
2424
alert( result.input ); // I love JavaScript(源字符串)
2525
```
2626

27-
2. 如果 `regexp` 带有 `pattern:g` 标记,则它将所有匹配项的数组作为字符串返回,而不包含分组和其他详细信息
27+
2. 如果 `regexp` 带有修饰符 `pattern:g`,则它将所有匹配项的数组以字符串的形式返回,而不包含捕获组和其它详细信息
2828
```js run
2929
let str = "I love JavaScript";
3030
@@ -34,7 +34,7 @@
3434
alert( result.length ); // 1
3535
```
3636

37-
3. 如果没有匹配项,则无论是否带有标记 `pattern:g` ,都将返回 `null`
37+
3. 如果没有匹配项,则无论是否带有修饰符 `pattern:g`,都将返回 `null`
3838

3939
这是一个重要的细微差别。如果没有匹配项,我们得到的不是一个空数组,而是 `null`。忘记这一点很容易出错,例如:
4040

@@ -57,15 +57,15 @@
5757

5858
[recent browser="new"]
5959

60-
方法 `str.matchAll(regexp)``str.match` “新改进的”变体
60+
方法 `str.matchAll(regexp)``str.match` 的“更新、改进”的变体
6161

6262
它主要用来搜索所有组的所有匹配项。
6363

6464
`match` 相比有 3 个区别:
6565

66-
1. 它返回包含匹配项的可迭代对象,而不是数组。我们可以用 `Array.from` 从中得到一个常规数组
67-
2. 每个匹配项均以包含分组的数组形式返回(返回格式与不带 `pattern:g` 标记的 `str.match` 相同)。
68-
3. 如果没有结果,则返回的不是 `null`,而是一个空的可迭代对象
66+
1. 它返回一个包含匹配项的可迭代对象,而不是数组。我们可以用 `Array.from` 将其转换为一个常规数组
67+
2. 每个匹配项均以一个包含捕获组的数组形式返回(返回格式与不带修饰符 `pattern:g` `str.match` 相同)。
68+
3. 如果没有结果,则返回的是一个空的可迭代对象而不是 `null`
6969

7070
用法示例:
7171

@@ -77,7 +77,7 @@ let matchAll = str.matchAll(regexp);
7777
7878
alert(matchAll); // [object RegExp String Iterator],不是数组,而是一个可迭代对象
7979
80-
matchAll = Array.from(matchAll); // 现在返回的是数组
80+
matchAll = Array.from(matchAll); // 现在是数组了
8181
8282
let firstMatch = matchAll[0];
8383
alert( firstMatch[0] ); // <h1>
@@ -86,27 +86,27 @@ alert( firstMatch.index ); // 0
8686
alert( firstMatch.input ); // <h1>Hello, world!</h1>
8787
```
8888

89-
如果我们用 `for..of` 来循环 `matchAll` 的匹配项,那么我们就不需要 `Array.from` 了。
89+
如果我们用 `for..of` 来遍历 `matchAll` 的匹配项,那么我们就不需要 `Array.from` 了。
9090

9191
## str.split(regexp|substr, limit)
9292

9393
使用正则表达式(或子字符串)作为分隔符来分割字符串。
9494

95-
我们可以用 `split` 来分割字符串,如下所示
95+
我们可以用 `split` 来分割字符串,像这样
9696

9797
```js run
9898
alert('12-34-56'.split('-')) // 数组 ['12', '34', '56']
9999
```
100100

101-
但同样,我们也可以用正则表达式来做
101+
但同样,我们也可以用正则表达式
102102

103103
```js run
104104
alert('12, 34, 56'.split(/,\s*/)) // 数组 ['12', '34', '56']
105105
```
106106

107107
## str.search(regexp)
108108

109-
方法 `str.search(regexp)` 返回第一个匹配项的位置,如果未找到,则返回 `-1`
109+
方法 `str.search(regexp)` 返回第一个匹配项的位置,如果没找到,则返回 `-1`
110110

111111
```js run
112112
let str = "A drop of ink may make a million think";
@@ -116,13 +116,13 @@ alert( str.search( /ink/i ) ); // 10(第一个匹配位置)
116116

117117
**重要限制:`search` 仅查找第一个匹配项。**
118118

119-
如果需要其他匹配项的位置,则应使用其他方法,例如用 `str.matchAll(regexp)` 查找所有位置。
119+
如果我们需要其他匹配项的位置,则应使用其他方法,例如用 `str.matchAll(regexp)` 查找所有位置。
120120

121121
## str.replace(str|regexp, str|func)
122122

123123
这是用于搜索和替换的通用方法,是最有用的方法之一。它是搜索和替换字符串的瑞士军刀。
124124

125-
我们可以不用正则表达式来搜索和替换子字符串
125+
们可以在不使用正则表达式的情况下使用它来搜索和替换子字符串
126126

127127
```js run
128128
// 用冒号替换连字符
@@ -131,26 +131,26 @@ alert('12-34-56'.replace("-", ":")) // 12:34-56
131131

132132
不过有一个陷阱。
133133

134-
**`replace` 的第一个参数是字符串时,它仅替换第一个匹配项**
134+
**`replace` 的第一个参数是字符串时,它只替换第一个匹配项**
135135

136-
您可以在上面的示例中看到:只有第一个 `"-"` `":"` 替换了
136+
你可以在上面的示例中看到:只有第一个 `"-"` 被替换为了 `":"`
137137

138-
如要找到所有的连字符,我们不应该用字符串 `"-"`,而应使用带 `pattern:g` 标记的正则表达式 `pattern:/-/g`
138+
如要找到所有的连字符,我们不应该用字符串 `"-"`,而应使用带 `pattern:g` 修饰符的正则表达式 `pattern:/-/g`
139139

140140
```js run
141-
// 将连字符替换为冒号
141+
// 将所有连字符都替换为冒号
142142
alert( '12-34-56'.replace( *!*/-/g*/!*, ":" ) ) // 12:34:56
143143
```
144144

145-
第二个参数是一个替代字符串。我们可以在其中使用特殊字符:
145+
第二个参数是替换字符串。我们可以在其中使用特殊字符:
146146

147-
| 符号 | 替换字符串中的操作 |
147+
| 符号 | 替换字符串中的行为 |
148148
|--------|--------|
149149
|`$&`|插入整个匹配项|
150-
|<code>$&#096;</code>|插入字符串中匹配项之前的字符串部分|
151-
|`$'`|插入字符串中匹配项之后的字符串部分|
152-
|`$n`|如果 `n` 是一个 12 位的数字,则插入第 n 个分组的内容,详见 [info:regexp-groups](info:regexp-groups)|
153-
|`$<name>`|插入带有给定 `name` 的括号内的内容,详见 [info:regexp-groups](info:regexp-groups)|
150+
|<code>$&#096;</code>|插入字符串中匹配项之前的字符串部分|
151+
|`$'`|插入字符串中匹配项之后的字符串部分|
152+
|`$n`|如果 `n` 是一个 1-2 位的数字,则插入第 n 个分组的内容,详见 <info:regexp-groups>|
153+
|`$<name>`|插入带有给定 `name` 的括号内的内容,详见 <info:regexp-groups>|
154154
|`$$`|插入字符 `$` |
155155

156156
例如:
@@ -168,11 +168,11 @@ alert(str.replace(/(john) (smith)/i, '$2, $1')) // Smith, John
168168

169169
该函数 `func(match, p1, p2, ..., pn, offset, input, groups)` 带参数调用:
170170

171-
1. `match` 匹配项,
172-
2. `p1, p2, ..., pn` - 分组的内容(如有),
173-
3. `offset` 匹配项的位置,
174-
4. `input` 源字符串,
175-
5. `groups` - 所指定分组的对象
171+
1. `match` —— 匹配项,
172+
2. `p1, p2, ..., pn` —— 捕获组的内容(如有),
173+
3. `offset` —— 匹配项的位置,
174+
4. `input` —— 源字符串,
175+
5. `groups` —— 具有命名的捕获组的对象
176176

177177
如果正则表达式中没有括号,则只有 3 个参数:`func(str, offset, input)`
178178

@@ -186,13 +186,13 @@ let result = str.replace(/html|css/gi, str => str.toUpperCase());
186186
alert(result); // HTML and CSS
187187
```
188188

189-
按其在字符串中的位置来替换每个匹配项
189+
将每个匹配项替换为其在字符串中的位置
190190

191191
```js run
192192
alert("Ho-Ho-ho".replace(/ho/gi, (match, offset) => offset)); // 0-3-6
193193
```
194194

195-
在下面的示例中,有两对括号,因此将使用 5 个参数调用替换函数:第一个是完全匹配项,然后是 2 对括号,然后是匹配位置(在示例中未使用)和源字符串
195+
在下面的示例中,有两对括号,因此将使用 5 个参数调用替换函数:第一个是完全匹配项,然后是 2 对括号,然后是(在示例中未使用)匹配位置和源字符串
196196

197197
```js run
198198
let str = "John Smith";
@@ -212,7 +212,7 @@ let result = str.replace(/(\w+) (\w+)/, (...match) => `${match[2]}, ${match[1]}`
212212
alert(result); // Smith, John
213213
```
214214

215-
或者,如果我们使用的是命名组,则带有它们的 `groups` 对象始终是最后一个对象,因此我们可以这样获得它
215+
或者,如果我们使用的是命名组,则带有它们的 `groups` 对象始终是最后一个对象,所以我们可以像这样获取它
216216

217217
```js run
218218
let str = "John Smith";
@@ -226,25 +226,42 @@ let result = str.replace(/(?<name>\w+) (?<surname>\w+)/, (...match) => {
226226
alert(result); // Smith, John
227227
```
228228

229-
使用函数可以为我们提供终极替代功能,因为它可以获取匹配项的所有信息,可以访问外部变量,可以做任何事。
229+
使用函数可以为我们提供终极替换功能,因为它可以获取匹配项的所有信息,可以访问外部变量,可以做任何事。
230+
231+
## str.replaceAll(str|regexp, str|func)
232+
233+
这个方法与 `str.replace` 本质上是一样的,但有两个主要的区别:
234+
235+
1. 如果第一个参数是一个字符串,它会替换 **所有出现的** 和第一个参数相同的字符串​,​而 `replace` 只会替换 **第一个**
236+
2. 如果第一个参数是一个没有修饰符 `g` 的正则表达式,则会报错。带有修饰符 `g`,它的工作方式与 `replace` 相同。
237+
238+
`replaceAll` 的主要用途是替换所有出现的字符串。
239+
240+
像这样:
241+
242+
```js run
243+
// 使用冒号替换所有破折号
244+
alert('12-34-56'.replaceAll("-", ":")) // 12:34:56
245+
```
246+
230247

231248
## regexp.exec(str)
232249

233-
`regexp.exec(str)` 方法返回字符串 `str` 中的 `regexp` 匹配项。与以前的方法不同,它是在正则表达式而不是字符串上调用的
250+
`regexp.exec(str)` 方法返回字符串 `str` 中的 `regexp` 匹配项。与以前的方法不同,它是在正则表达式而不是在字符串上调用的
234251

235-
根据正则表达式是否带有标志 `pattern:g`,它的行为有所不同
252+
它的行为取决于正则表达式是否具有修饰符 `pattern:g`
236253

237-
如果没有 `pattern:g`那么 `regexp.exec(str)` 返回的第一个匹配与 `str.match(regexp)` 完全相同。这没什么新的变化
254+
如果没有修饰符 `pattern:g` `regexp.exec(str)` 会返回与 第一个匹配项,就像 `str.match(regexp)` 那样。这种行为并没有带来任何新的东西
238255

239-
但是,如果有标记 `pattern:g`,那么:
256+
但是,如果有修饰符 `pattern:g`,那么:
240257
- 调用 `regexp.exec(str)` 会返回第一个匹配项,并将紧随其后的位置保存在属性 `regexp.lastIndex` 中。
241-
- 下一次同样的调用会从位置 `regexp.lastIndex` 开始搜索,返回下一个匹配项,并将其后的位置保存在 `regexp.lastIndex` 中。
242-
- ...以此类推。
258+
- 下一次这样的调用会从位置 `regexp.lastIndex` 开始搜索,返回下一个匹配项,并将其后的位置保存在 `regexp.lastIndex` 中。
259+
- ……以此类推。
243260
- 如果没有匹配项,则 `regexp.exec` 返回 `null`,并将 `regexp.lastIndex` 重置为 `0`
244261

245-
因此,重复调用会挨个返回所有的匹配项,属性 `regexp.lastIndex` 用来跟踪当前的搜索位置
262+
因此,重复调用会一个接一个地返回所有匹配项,使用属性 `regexp.lastIndex` 来跟踪当前搜索位置
246263

247-
过去,在将 `str.matchAll` 方法添加到 `JavaScript` 之前,在循环中是通过调用 `regexp.exec` 来获取分组的所有匹配项
264+
过去,在将 `str.matchAll` 方法添加到 JavaScript 之前,会在循环中调用 `regexp.exec` 来获取组的所有匹配项
248265

249266
```js run
250267
let str = 'More about JavaScript at https://javascript.info';
@@ -254,12 +271,12 @@ let result;
254271
255272
while (result = regexp.exec(str)) {
256273
alert( `Found ${result[0]} at position ${result.index}` );
257-
// Found JavaScript at position 11,然后
258-
// Found javascript at position 33
274+
// 在位置 11 找到了 JavaScript,然后
275+
// 在位置 33 找到了 javascript
259276
}
260277
```
261278

262-
这个现在也可以使用,尽管对于较新的浏览器来说,`str.matchAll` 通常更方便。
279+
这现在也有效,尽管对于较新的浏览器 `str.matchAll` 通常更方便。
263280

264281
**我们可以通过手动设置 `lastIndex`,用 `regexp.exec` 从给定位置进行搜索。**
265282

@@ -268,15 +285,15 @@ while (result = regexp.exec(str)) {
268285
```js run
269286
let str = 'Hello, world!';
270287
271-
let regexp = /\w+/g; // 不带标记 "g",lastIndex 属性会被忽略
288+
let regexp = /\w+/g; // 没有修饰符 "g",lastIndex 属性会被忽略
272289
regexp.lastIndex = 5; // 从第 5 个位置搜索(从逗号开始)
273290
274291
alert( regexp.exec(str) ); // world
275292
```
276293

277-
如果正则表达式带有标记 `pattern:y`,则搜索将精确地在 `regexp.lastIndex` 位置执行,不会再继续了
294+
如果正则表达式带有修饰符 `pattern:y`,则搜索将精确地在 `regexp.lastIndex` 位置执行,不会再进一步
278295

279-
让我们将上例中的 `pattern:g` 标记替换为 `pattern:y`现在没有找到匹配项了,因为在位置 `5` 处没有单词:
296+
让我们将上面示例中的 `pattern:g` 修饰符替换为 `pattern:y`现在没有找到匹配项,因为在位置 `5` 处没有单词:
280297

281298
```js run
282299
let str = 'Hello, world!';
@@ -287,7 +304,7 @@ regexp.lastIndex = 5; // 在位置 5 精确查找
287304
alert( regexp.exec(str) ); // null
288305
```
289306

290-
这个方法在某些场景下很方便,例如需要用正则表达式从字符串的精确位置来“读取”字符串(而不是其后的某处)
307+
当我们需要通过正则表达式在确切位置而不是其后的某处从字符串中“读取”某些内容时,这很方便
291308

292309
## regexp.test(str)
293310

@@ -303,7 +320,7 @@ alert( *!*/love/i*/!*.test(str) ); // true
303320
alert( str.search(*!*/love/i*/!*) != -1 ); // true
304321
```
305322

306-
一个反例
323+
一个否定答案的例子
307324

308325
```js run
309326
let str = "Bla-bla-bla";
@@ -312,32 +329,33 @@ alert( *!*/love/i*/!*.test(str) ); // false
312329
alert( str.search(*!*/love/i*/!*) != -1 ); // false
313330
```
314331

315-
如果正则表达式带有标记 `pattern:g`,则 `regexp.test``regexp.lastIndex` 属性中查找,并更新此属性,就像 `regexp.exec` 一样。
332+
如果正则表达式带有修饰符 `pattern:g`,则 `regexp.test``regexp.lastIndex` 属性开始查找并更新此属性,就像 `regexp.exec` 一样。
316333

317-
因此,我们可以用它从给定位置进行搜索
334+
因此,我们可以用它从给定位置进行查找
318335

319336
```js run
320337
let regexp = /love/gi;
321338
322339
let str = "I love JavaScript";
323340
324-
// 从位置 10 开始
341+
// 从位置 10 开始搜索
325342
regexp.lastIndex = 10;
326-
alert( regexp.test(str) ); // false(无匹配
343+
alert( regexp.test(str) ); // false(没有匹配项
327344
```
328345

329346
````warn header="相同的全局正则表达式在不同的源字符串上测试可能会失败"
330-
如果我们在不同的源字符串上应用相同的全局表达式,可能会出现错误的结果,因为 `regexp.test` 的调用会增加 `regexp.lastIndex` 属性值,因此在另一个字符串中的搜索可能是从非 0 位置开始的。
347+
如果我们在不同的源字符串上应用相同的全局正则表达式,可能会出现错误的结果,因为 `regexp.test` 的调用会增加 `regexp.lastIndex` 属性值,因此在另一个字符串中的搜索可能是从非 0 位置开始的。
331348

332349
例如,这里我们在同一文本上调用 `regexp.test` 两次,而第二次调用失败了:
333350

334351
```js run
335-
let regexp = /javascript/g; // (新建 regexp:regexp.lastIndex=0)
352+
let regexp = /javascript/g; // (新建立的 regexp:regexp.lastIndex=0)
336353
337354
alert( regexp.test("javascript") ); // true(现在 regexp.lastIndex=10)
338355
alert( regexp.test("javascript") ); // false
339356
```
340357

341358
这正是因为在第二个测试中 `regexp.lastIndex` 不为零。
342359

343-
如要解决这个问题,我们可以在每次搜索之前设置 `regexp.lastIndex = 0`。或者,不调用正则表达式的方法,而是使用字符串方法 `str.match/search/...`,这些方法不用 `lastIndex`
360+
如要解决这个问题,我们可以在每次搜索之前设置 `regexp.lastIndex = 0`。或者,不要在正则表达式上调用方法,而是使用字符串方法 `str.match/search/...`,这些方法不使用 `lastIndex`
361+
````

0 commit comments

Comments
 (0)