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" ;
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
3434 alert( result.length ); // 1
3535 ` ` `
3636
37- 3. 如果没有匹配项,则无论是否带有标记 ` pattern:g` ,都将返回 ` null` 。
37+ 3. 如果没有匹配项,则无论是否带有修饰符 ` pattern:g` ,都将返回 ` null` 。
3838
3939 这是一个重要的细微差别。如果没有匹配项,我们得到的不是一个空数组,而是 ` null` 。忘记这一点很容易出错,例如:
4040
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
7878alert(matchAll); // [object RegExp String Iterator],不是数组,而是一个可迭代对象
7979
80- matchAll = Array.from(matchAll); // 现在返回的是数组
80+ matchAll = Array.from(matchAll); // 现在是数组了
8181
8282let firstMatch = matchAll[0];
8383alert( firstMatch[0] ); // <h1>
@@ -86,27 +86,27 @@ alert( firstMatch.index ); // 0
8686alert( 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
9898alert('12-34-56'.split('-')) // 数组 ['12', '34', '56']
9999` ` `
100100
101- 但同样,我们也可以用正则表达式来做 :
101+ 但同样,我们也可以用正则表达式 :
102102
103103` ` ` js run
104104alert('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
112112let 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+ // 将所有连字符都替换为冒号
142142alert( '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` 是一个 1 到 2 位的数字,则插入第 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());
186186alert(result); // HTML and CSS
187187` ` `
188188
189- 按其在字符串中的位置来替换每个匹配项 :
189+ 将每个匹配项替换为其在字符串中的位置 :
190190
191191` ` ` js run
192192alert("Ho-Ho-ho".replace(/ho/gi, (match, offset) => offset)); // 0-3-6
193193` ` `
194194
195- 在下面的示例中,有两对括号,因此将使用 5 个参数调用替换函数:第一个是完全匹配项,然后是 2 对括号,然后是匹配位置 (在示例中未使用)和源字符串 :
195+ 在下面的示例中,有两对括号,因此将使用 5 个参数调用替换函数:第一个是完全匹配项,然后是 2 对括号,然后是 (在示例中未使用)匹配位置和源字符串 :
196196
197197` ` ` js run
198198let str = "John Smith";
@@ -212,7 +212,7 @@ let result = str.replace(/(\w+) (\w+)/, (...match) => `${match[2]}, ${match[1]}`
212212alert(result); // Smith, John
213213` ` `
214214
215- 或者,如果我们使用的是命名组,则带有它们的 ` groups` 对象始终是最后一个对象,因此我们可以这样获得它 :
215+ 或者,如果我们使用的是命名组,则带有它们的 ` groups` 对象始终是最后一个对象,所以我们可以像这样获取它 :
216216
217217` ` ` js run
218218let str = "John Smith";
@@ -226,25 +226,42 @@ let result = str.replace(/(?<name>\w+) (?<surname>\w+)/, (...match) => {
226226alert(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
250267let str = 'More about JavaScript at https://javascript.info';
@@ -254,12 +271,12 @@ let result;
254271
255272while (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
269286let str = 'Hello, world!';
270287
271- let regexp = /\w +/g; // 不带标记 "g",lastIndex 属性会被忽略
288+ let regexp = /\w +/g; // 没有修饰符 "g",lastIndex 属性会被忽略
272289regexp.lastIndex = 5; // 从第 5 个位置搜索(从逗号开始)
273290
274291alert( 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
282299let str = 'Hello, world!';
@@ -287,7 +304,7 @@ regexp.lastIndex = 5; // 在位置 5 精确查找
287304alert( regexp.exec(str) ); // null
288305` ` `
289306
290- 这个方法在某些场景下很方便,例如需要用正则表达式从字符串的精确位置来 “读取”字符串(而不是其后的某处) 。
307+ 当我们需要通过正则表达式在确切位置而不是其后的某处从字符串中 “读取”某些内容时,这很方便 。
291308
292309## regexp .test (str)
293310
@@ -303,7 +320,7 @@ alert( *!*/love/i*/!*.test(str) ); // true
303320alert( str.search(*!*/love/i*/!*) != -1 ); // true
304321` ` `
305322
306- 一个反例 :
323+ 一个否定答案的例子 :
307324
308325` ` ` js run
309326let str = "Bla-bla-bla";
@@ -312,32 +329,33 @@ alert( *!*/love/i*/!*.test(str) ); // false
312329alert( 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
320337let regexp = /love/gi;
321338
322339let str = "I love JavaScript";
323340
324- // 从位置 10 开始 :
341+ // 从位置 10 开始搜索 :
325342regexp.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
337354alert( regexp.test("javascript") ); // true(现在 regexp.lastIndex=10)
338355alert( 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