diff --git a/files/zh-cn/web/javascript/reference/global_objects/string/match/index.md b/files/zh-cn/web/javascript/reference/global_objects/string/match/index.md index 0f0c585705d9ef..8f170d15eb1e12 100644 --- a/files/zh-cn/web/javascript/reference/global_objects/string/match/index.md +++ b/files/zh-cn/web/javascript/reference/global_objects/string/match/index.md @@ -5,14 +5,14 @@ slug: Web/JavaScript/Reference/Global_Objects/String/match {{JSRef}} -**`match()`** 方法检索返回一个字符串匹配正则表达式的结果。 +**`match()`** 方法检索字符串与[正则表达式](/zh-CN/docs/Web/JavaScript/Guide/Regular_expressions)的匹配结果。 {{EmbedInteractiveExample("pages/js/string-match.html", "shorter")}} ## 语法 -```plain -str.match(regexp) +```js-nolint +match(regexp) ``` ### 参数 @@ -26,92 +26,123 @@ str.match(regexp) ### 返回值 -- 如果使用 g 标志,则将返回与完整正则表达式匹配的所有结果,但不会返回捕获组。 -- 如果未使用 g 标志,则仅返回第一个完整匹配及其相关的捕获组(`Array`)。在这种情况下,返回的项目将具有如下所述的其他属性。 +一个 {{jsxref("Array")}},其内容取决于全局 (`g`) 标志的存在或缺失,如果没有匹配,则返回 [`null`](/zh-CN/docs/Web/JavaScript/Reference/Operators/null)。 -#### 附加属性 - -如上所述,匹配的结果包含如下所述的附加特性。 - -- `groups`: 一个命名捕获组对象,其键是捕获组名称,值是捕获组,如果未定义命名捕获组,则为 {{jsxref("undefined")}}。有关详细信息,请参阅[组和范围](/zh-CN/docs/Web/JavaScript/Guide/Regular_expressions/Groups_and_Ranges)。 -- `index`: 匹配的结果的开始位置 -- `input`: 搜索的字符串。 - -一个{{jsxref("Array")}},其内容取决于 global(`g`)标志的存在与否,如果未找到匹配则为{{jsxref("null")}}。 +- 如果使用 `g` 标志,则将返回与完整正则表达式匹配的所有结果,但不会返回捕获组。 +- 如果没有使用 `g` 标志,则只返回第一个完整匹配及其相关捕获组。在这种情况下,`match()` 方法将返回与 {{jsxref("RegExp.prototype.exec()")}} 相同的结果(一个带有一些额外属性的数组)。 ## 描述 -如果正则表达式不包含 `g` 标志,`str.match()` 将返回与 {{jsxref("RegExp.prototype.exec()", "RegExp.exec()")}}. 相同的结果。 +`String.prototype.match` 方法本身的实现非常简单,它只是使用字符串作为第一个参数调用了参数的 `Symbol.match` 方法。实际的实现来自于 [`RegExp.prototype[@@match]()`](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@match)。 -### 参看:`RegExp` 方法 +- 如果你需要知道一个字符串是否与一个正则表达式 {{jsxref("RegExp")}} 匹配,使用 {{jsxref("RegExp.prototype.test()")}}。 +- 如果你只想获取第一个匹配项,你可能需要使用 {{jsxref("RegExp.prototype.exec()")}}。 +- 如果你想要获取捕获组,并且全局标志已设置,你需要使用 {{jsxref("RegExp.prototype.exec()")}} 或 {{jsxref("String.prototype.matchAll()")}}。 -- 如果你需要知道一个字符串是否与一个正则表达式匹配 {{jsxref("RegExp")}} ,可使用 {{jsxref("RegExp.prototype.test()", "RegExp.test()")}} 。 -- 如果你只是需要第一个匹配结果,你也可以使用 {{jsxref("RegExp.prototype.exec()", "RegExp.exec()")}} 。 -- 如果你想要获得捕获组,并且设置了全局标志,你需要用 {{jsxref("RegExp.prototype.exec()", "RegExp.exec()")}} 或者 {{jsxref("String.prototype.matchAll()", " String.prototype.matchAll()")}} +有关传入正则表达式时 `match()` 方法的语义更多信息,请参阅 [`RegExp.prototype[@@match]()`](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@match)。 ## 示例 -### 示例:使用 `match` +### 使用 match() 在下例中,使用 `match` 查找 "`Chapter`" 紧跟着 1 个或多个数值字符,再紧跟着一个小数点和数值字符 0 次或多次。正则表达式包含 `i` 标志,因此大小写会被忽略。 ```js -var str = 'For more information, see Chapter 3.4.5.1'; -var re = /see (chapter \d+(\.\d)*)/i; -var found = str.match(re); +const str = "For more information, see Chapter 3.4.5.1"; +const re = /see (chapter \d+(\.\d)*)/i; +const found = str.match(re); console.log(found); - -// logs [ 'see Chapter 3.4.5.1', -// 'Chapter 3.4.5.1', -// '.1', -// index: 22, -// input: 'For more information, see Chapter 3.4.5.1' ] - -// 'see Chapter 3.4.5.1' 是整个匹配。 -// 'Chapter 3.4.5.1' 被'(chapter \d+(\.\d)*)'捕获。 -// '.1' 是被'(\.\d)'捕获的最后一个值。 -// 'index' 属性 (22) 是整个匹配从零开始的索引。 -// 'input' 属性是被解析的原始字符串。 +// [ +// 'see Chapter 3.4.5.1', +// 'Chapter 3.4.5.1', +// '.1', +// index: 22, +// input: 'For more information, see Chapter 3.4.5.1', +// groups: undefined +// ] ``` -### 示例:`match` 使用全局(global)和忽略大小写(ignore case)标志 +在上面的匹配结果中,`'see Chapter 3.4.5.1'` 是整个匹配。`'Chapter 3.4.5.1'` 被 `(chapter \d+(\.\d)*)` 捕获。`.1` 是由 `(\.\d)` 最后捕获的值。`index` 属性 (`22`) 是整个匹配的零基索引。`input` 属性是解析的原始字符串。 -下例展示了 `match` 使用 global 和 ignore case 标志。A-E、a-e 的所有字母将会作为一个数组的元素返回。 +### 使用全局标志和忽略大小写标志掉用 match() + +下面的示例演示了在 `match()` 中使用全局标志和忽略大小写标志。所有字母 `A` 到 `E` 和 `a` 到 `e` 都将作为数组中的一个元素返回。 ```js -var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; -var regexp = /[A-E]/gi; -var matches_array = str.match(regexp); +const str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; +const regexp = /[A-E]/gi; +const matches = str.match(regexp); -console.log(matches_array); +console.log(matches); // ['A', 'B', 'C', 'D', 'E', 'a', 'b', 'c', 'd', 'e'] ``` -### 使用 `match()`,不传参数 +> **备注:** 还可以参见 {{jsxref("String.prototype.matchAll()")}} 和[通过标志进行高级搜索](/zh-CN/docs/Web/JavaScript/Guide/Regular_expressions#通过标志进行高级搜索)。 + +### 使用命名捕获组 + +在支持命名捕获组的浏览器中,以下代码将 `"fox"` 或 `"cat"` 捕获到一个名为 `animal` 的组中: ```js -var str = "Nothing will come of nothing."; +const paragraph = "The quick brown fox jumps over the lazy dog. It barked."; -str.match(); // returns [""] +const capturingRegex = /(?fox|cat) jumps over/; +const found = paragraph.match(capturingRegex); +console.log(found.groups); // {animal: "fox"} + +### 使用 match(),不传参数 + +```js +const str = "空即是空"; + +str.match(); // 返回 [""] +``` + +### 使用实现了 @@match 的非 RegExp 对象调用 match() + +如果一个对象有一个名为 `Symbol.match` 的方法,那么它可以被用作自定义匹配器。`Symbol.match` 的返回值将成为 `match()` 方法的返回值。 + +```js +const str = "Hmm, this is interesting."; + +str.match({ + [Symbol.match](str) { + return ["Yes, it's interesting."]; + }, +}); // returns ["Yes, it's interesting."] ``` ### 一个非正则表达式对象作为参数 -当参数是一个字符串或一个数字,它会使用 new RegExp(obj) 来隐式转换成一个 {{jsxref("RegExp")}}。如果它是一个有正号的正数,RegExp() 方法将忽略正号。 +当 `regexp` 参数是一个字符串或一个数字,它会使用 `new RegExp(regexp)` 来隐式转换成一个 {{jsxref("RegExp")}}。 + +```js +const str1 = + "NaN 表示不是一个数字。在 JavaScript 中 Infinity 包括了 -Infinity 和 +Infinity。"; +const str2 = + "我的爷爷已经 65 岁了,我的奶奶已经 63 岁"; +const str3 = "该合同被声明为 null 且 void。"; +str1.match("数字"); // “数字” 是一个字符串。返回 ["number"] +str1.match(NaN); // NaN 的类型是数字。返回 ["NaN"] +str1.match(Infinity); // Infinity 的类型是数字。返回 ["Infinity"] +str1.match(+Infinity); // 返回 ["Infinity"] +str1.match(-Infinity); // 返回 ["-Infinity"] +str2.match(65); // 返回 ["65"] +str2.match(+65); // 带正号的数字。返回 ["65"] +str3.match(null); // 返回 ["null"] +``` + +如果特殊字符没有被正确转义,这可能会导致意想不到的结果。 + +```js +console.log("123".match("1.3")); // [ "123" ] +``` + +这是一个匹配,因为正则表达式中的 `.` 可以匹配任何字符。为了仅匹配一个点字符,需要对输入进行转义。 ```js -var str1 = "NaN means not a number. Infinity contains -Infinity and +Infinity in JavaScript.", - str2 = "My grandfather is 65 years old and My grandmother is 63 years old.", - str3 = "The contract was declared null and void."; -str1.match("number"); // "number" 是字符串。返回 ["number"] -str1.match(NaN); // NaN 的类型是 number。返回 ["NaN"] -str1.match(Infinity); // Infinity 的类型是 number。返回 ["Infinity"] -str1.match(+Infinity); // 返回 ["Infinity"] -str1.match(-Infinity); // 返回 ["-Infinity"] -str2.match(65); // 返回 ["65"] -str2.match(+65); // 有正号的 number。返回 ["65"] -str3.match(null); // 返回 ["null"] +console.log("123".match("1\\.3")); // null ``` ## 规范 @@ -122,8 +153,10 @@ str3.match(null); // 返回 ["null"] {{Compat}} -## 相关链接 +## 参见 +- [在 `core-js` 中实现 `String.prototype.match` 的 polyfill,包括修复和实现现代行为,例如 `Symbol.match` 支持](https://github.com/zloirock/core-js#ecmascript-string-and-regexp) +- {{jsxref("String.prototype.matchAll()")}} - {{jsxref("RegExp")}} - {{jsxref("RegExp.prototype.exec()")}} - {{jsxref("RegExp.prototype.test()")}}