diff --git a/5-regular-expressions/01-regexp-introduction/article.md b/5-regular-expressions/01-regexp-introduction/article.md index 5b6c9473b6..21d33804fa 100644 --- a/5-regular-expressions/01-regexp-introduction/article.md +++ b/5-regular-expressions/01-regexp-introduction/article.md @@ -1,129 +1,129 @@ -# Patterns and flags +# 模式(Patterns)和修饰符(flags) -Regular expressions is a powerful way of searching and replacing inside a string. +正则表达式是搜索和替换字符串的一种强大方式。 -In JavaScript regular expressions are implemented using objects of a built-in `RegExp` class and integrated with strings. +在 JavaScript 中,正则表达式通过内置的“RegExp”类的对象来实现,并与字符串集成。 -Please note that regular expressions vary between programming languages. In this tutorial we concentrate on JavaScript. Of course there's a lot in common, but they are a somewhat different in Perl, Ruby, PHP etc. +请注意,在各编程语言之间,正则表达式是有所不同的。在本教程中,我们只专注于 JavaScript。当然,它们有很多共同点,但在 Perl、Ruby 和 PHP 等语言下会有所不同。 -## Regular expressions +## 正则表达式 -A regular expression (also "regexp", or just "reg") consists of a *pattern* and optional *flags*. +正则表达式(可叫作“regexp”或者“reg”)包含 **模式** 和可选的 **修饰符**。 -There are two syntaxes to create a regular expression object. +创建一个正则表达式对象有两种语法。 -The long syntax: +较长一点的语法: ```js regexp = new RegExp("pattern", "flags"); ``` -...And the short one, using slashes `"/"`: +...较短一点的语法,使用斜杠 `"/"`: ```js -regexp = /pattern/; // no flags -regexp = /pattern/gmi; // with flags g,m and i (to be covered soon) +regexp = /pattern/; // 没有修饰符 +regexp = /pattern/gmi; // 伴随修饰符 g、m 和 i(后面会讲到) ``` -Slashes `"/"` tell JavaScript that we are creating a regular expression. They play the same role as quotes for strings. +斜杠 `"/"` 会告诉 JavaScript 我们正在创建一个正则表达式。它的作用类似于字符串的引号。 -## Usage +## 用法 -To search inside a string, we can use method [search](mdn:js/String/search). +如果要在字符串中进行搜索,可以使用 [search](mdn:js/String/search) 方法。 -Here's an example: +下面是示例: ```js run -let str = "I love JavaScript!"; // will search here +let str = "I love JavaScript!"; // 将在这里搜索 let regexp = /love/; alert( str.search(regexp) ); // 2 ``` -The `str.search` method looks for the pattern `pattern:/love/` and returns the position inside the string. As we might guess, `pattern:/love/` is the simplest possible pattern. What it does is a simple substring search. +`str.search` 方法会查找模式 `pattern:/love/`,然后返回匹配项在字符串中的位置。我们可以猜到,`pattern:/love/` 是最简单的模式。它所做的就是简单的子字符串的查找。 -The code above is the same as: +上面的代码等同于: ```js run -let str = "I love JavaScript!"; // will search here +let str = "I love JavaScript!"; // 将在这里搜索 let substr = 'love'; alert( str.search(substr) ); // 2 ``` -So searching for `pattern:/love/` is the same as searching for `"love"`. +所以搜索 `pattern:/love/` 与搜索 `"love"` 是等价的。 -But that's only for now. Soon we'll create more complex regular expressions with much searching more power. +但这只是暂时的。很快我们就会接触更复杂的正则表达式,其搜索功能将更强大。 -```smart header="Colors" -From here on the color scheme is: +```smart header="配色" +本文中的配色方案如下: - regexp -- `pattern:red` -- string (where we search) -- `subject:blue` +- string(我们要搜索的)-- `subject:blue` - result -- `match:green` ``` -````smart header="When to use `new RegExp`?" -Normally we use the short syntax `/.../`. But it does not allow any variables insertions, so we must know the exact regexp at the time of writing the code. +````smart header="什么时候使用 `new RegExp`?" +通常我们使用的都是简短语法 `/.../`。但是它不接受任何变量插入,所以我们必须在写代码的时候就知道确切的 regexp。 -From the other hand, `new RegExp` allows to construct a pattern dynamically from a string. +另一方面,`new RegExp` 允许从字符串中动态地构造模式。 -So we can figure out what we need to search and create `new RegExp` from it: +所以我们可以找出需要搜索的字段,然后根据搜索字段创建 `new RegExp`: ```js run let search = prompt("What you want to search?", "love"); let regexp = new RegExp(search); -// find whatever the user wants +// 找到用户想要的任何东西 alert( "I love JavaScript".search(regexp)); ``` ```` -## Flags +## 修饰符 -Regular expressions may have flags that affect the search. +正则表达式的修饰符可能会影响搜索结果。 -There are only 5 of them in JavaScript: +在 JavaScript 中,有 5 个修饰符: `i` -: With this flag the search is case-insensitive: no difference between `A` and `a` (see the example below). +: 使用此修饰符后,搜索时不区分大小写: `A` 和 `a` 没有区别(具体看下面的例子)。 `g` -: With this flag the search looks for all matches, without it -- only the first one (we'll see uses in the next chapter). +: 使用此修饰符后,搜索时会查找所有的匹配项,而不只是第一个(在下一章会讲到)。 `m` -: Multiline mode (covered in the chapter ). +: 多行模式(详见章节 )。 `u` -: Enables full unicode support. The flag enables correct processing of surrogate pairs. More about that in the chapter . +: 开启完整的 unicode 支持。该修饰符能够修正对于代理对的处理。更详细的内容见章节 。 `y` -: Sticky mode (covered in the [next chapter](info:regexp-methods#y-flag)) +: 粘滞模式(详见 [下一章节](info:regexp-methods#y-flag)) -## The "i" flag +## “i”修饰符 -The simplest flag is `i`. +最简单的修饰符就是 `i` 了。 -An example with it: +示例代码如下: ```js run let str = "I love JavaScript!"; -alert( str.search(/LOVE/) ); // -1 (not found) +alert( str.search(/LOVE/) ); // -1(没找到) alert( str.search(/LOVE/i) ); // 2 ``` -1. The first search returns `-1` (not found), because the search is case-sensitive by default. -2. With the flag `pattern:/LOVE/i` the search found `match:love` at position 2. +1. 第一个搜索返回的是 `-1`(也就是没找到),因为搜索默认是区分大小写的。 +2. 使用修饰符 `pattern:/LOVE/i`,在字符串的第 2 个位置上搜索到了 `match:love`。 -So the `i` flag already makes regular expressions more powerful than a simple substring search. But there's so much more. We'll cover other flags and features in the next chapters. +相比与简单的子字符串查找,`i` 修饰符已经让正则表达式变得更加强大了。但是这还不够。我们会在下一章节讲述其它修饰符和特性。 -## Summary +## 总结 -- A regular expression consists of a pattern and optional flags: `g`, `i`, `m`, `u`, `y`. -- Without flags and special symbols that we'll study later, the search by a regexp is the same as a substring search. -- The method `str.search(regexp)` returns the index where the match is found or `-1` if there's no match. +- 一个正则表达式包含模式和可选修饰符:`g`、`i`、`m`、`u`、`y`。 +- 如果不使用我们在后面将要学到的修饰符和特殊标志,正则表达式的搜索就等同于子字符串查找。 +- `str.search(regexp)` 方法返回的是找到的匹配项的索引位置,如果没找到则返回 `-1`。 diff --git a/5-regular-expressions/02-regexp-methods/article.md b/5-regular-expressions/02-regexp-methods/article.md index c5a4cbdc67..b5adff4126 100644 --- a/5-regular-expressions/02-regexp-methods/article.md +++ b/5-regular-expressions/02-regexp-methods/article.md @@ -1,85 +1,85 @@ -# Methods of RegExp and String +# RegExp 和 String 的方法 -There are two sets of methods to deal with regular expressions. +有两组方法可以处理正则表达式。 -1. First, regular expressions are objects of the built-in [RegExp](mdn:js/RegExp) class, it provides many methods. -2. Besides that, there are methods in regular strings can work with regexps. +1. 首先,正则表达式是内置的 [RegExp](mdn:js/RegExp) 类的对象,它提供了许多方法。 +2. 除此之外,正则字符串中的一些方法可以与regexp一起工作。 -The structure is a bit messed up, so we'll first consider methods separately, and then -- practical recipes for common tasks. +为了避免结构混乱,我们首先会单独讨论一些方法,然后再讨论通用任务的使用方法。 ## str.search(reg) -We've seen this method already. It returns the position of the first match or `-1` if none found: +在上一章节中我们已经见过这个方法了。它返回第一个匹配项所在的位置,如果没有找到则返回 `-1`。 ```js run let str = "A drop of ink may make a million think"; -alert( str.search( *!*/a/i*/!* ) ); // 0 (the first position) +alert( str.search( *!*/a/i*/!* ) ); // 0(最开始的位置) ``` -**The important limitation: `search` always looks for the first match.** +**重要提示:`search` 总是查找第一个匹配项。** -We can't find next positions using `search`, there's just no syntax for that. But there are other methods that can. +我们不能使用 `search` 来查找下一个匹配项的位置,没有这样的语法。但是还有其它方法可以做到。 -## str.match(reg), no "g" flag +## 没有“g”修饰符情况下的 str.match(reg) -The method `str.match` behavior varies depending on the `g` flag. First let's see the case without it. +`str.match` 方法的行为取决于是否有 `g` 修饰符。首先我们来看一下没有修饰符的情况。 -Then `str.match(reg)` looks for the first match only. +`str.match(reg)` 只会查找第一个匹配项。 -The result is an array with that match and additional properties: +结果是一个数组,里面有该匹配项和额外的属性: -- `index` -- the position of the match inside the string, -- `input` -- the subject string. +- `index` -- 匹配项在字符串中所处在的位置, +- `input` -- 原始字符串。 -For instance: +例如: ```js run let str = "Fame is the thirst of youth"; let result = str.match( *!*/fame/i*/!* ); -alert( result[0] ); // Fame (the match) -alert( result.index ); // 0 (at the zero position) -alert( result.input ); // "Fame is the thirst of youth" (the string) +alert( result[0] ); // Fame(匹配项) +alert( result.index ); // 0(在最开始的位置 0) +alert( result.input ); // “Fame is the thirst of youth”(字符串本身) ``` -The array may have more than one element. +该数组可能有不止一项元素。 -**If a part of the pattern is delimited by parentheses `(...)`, then it becomes a separate element of the array.** +**如果模式的一部分被括号 `(...)` 括起来了,那么这部分将会独占数组的一个元素。** -For instance: +例如: ```js run let str = "JavaScript is a programming language"; let result = str.match( *!*/JAVA(SCRIPT)/i*/!* ); -alert( result[0] ); // JavaScript (the whole match) -alert( result[1] ); // script (the part of the match that corresponds to the parentheses) +alert( result[0] ); // JavaScript(整个匹配项) +alert( result[1] ); // script(对应括号里的匹配项) alert( result.index ); // 0 alert( result.input ); // JavaScript is a programming language ``` -Due to the `i` flag the search is case-insensitive, so it finds `match:JavaScript`. The part of the match that corresponds to `pattern:SCRIPT` becomes a separate array item. +由于 `i` 修饰符,搜索不区分大小写,因此它会找到 `match:JavaScript`。与 `pattern:SCRIPT` 相对应的匹配部分独占数组中的一项。 -We'll be back to parentheses later in the chapter . They are great for search-and-replace. +稍后我们会在 章节继续讲述圆括号这部分。圆括号非常适合搜索和替换。 -## str.match(reg) with "g" flag +## 使用“g”修饰符的 str.match(reg) -When there's a `"g"` flag, then `str.match` returns an array of all matches. There are no additional properties in that array, and parentheses do not create any elements. +当使用 `"g"` 修饰符的时候,`str.match` 就会返回由所有匹配项组成的数组。在数组中没有额外的属性,而且圆括号也不会创建任何元素。 -For instance: +例如: ```js run let str = "HO-Ho-ho!"; let result = str.match( *!*/ho/ig*/!* ); -alert( result ); // HO, Ho, ho (all matches, case-insensitive) +alert( result ); // HO, Ho, ho(所有的匹配项,大小写不敏感) ``` -With parentheses nothing changes, here we go: +使用括号也不会有什么改变: ```js run let str = "HO-Ho-ho!"; @@ -89,14 +89,14 @@ let result = str.match( *!*/h(o)/ig*/!* ); alert( result ); // HO, Ho, ho ``` -So, with `g` flag the `result` is a simple array of matches. No additional properties. +所以,使用 `g` 修饰符,`result` 就仅仅是一个由匹配项组成的数组。没有额外的属性。 -If we want to get information about match positions and use parentheses then we should use [RegExp#exec](mdn:js/RegExp/exec) method that we'll cover below. +如果我们想获取匹配项位置的更多信息,并且使用括号,那么我们应该使用下面将要提到的 [RegExp#exec](mdn:js/RegExp/exec) 方法。 -````warn header="If there are no matches, the call to `match` returns `null`" -Please note, that's important. If there were no matches, the result is not an empty array, but `null`. +````warn header="如果没有匹配项,那么调用 `match` 会返回 `null`" +请注意,这很重要。如果没有匹配项,结果不是一个空数组,而是 `null`。 -Keep that in mind to evade pitfalls like this: +记住这一点,避免发生下面的错误: ```js run let str = "Hey-hey-hey!"; @@ -107,15 +107,15 @@ alert( str.match(/ho/gi).length ); // error! there's no length of null ## str.split(regexp|substr, limit) -Splits the string using the regexp (or a substring) as a delimiter. +使用 regexp(或子字符串)作为分隔符分隔字符串。 -We already used `split` with strings, like this: +我们之前已经使用过 `split` 的字符串形式,像下面这样: ```js run alert('12-34-56'.split('-')) // [12, 34, 56] ``` -But we can also pass a regular expression: +但是我们也可以传入一个正则表达式: ```js run alert('12-34-56'.split(/-/)) // [12, 34, 56] @@ -123,47 +123,47 @@ alert('12-34-56'.split(/-/)) // [12, 34, 56] ## str.replace(str|reg, str|func) -The swiss army knife for search and replace in strings. +这简直是搜索和替换字符串的利器。 -The simplest use -- search and replace a substring, like this: +最简单的用处 — 搜索和替换子字符串,就像下面这样: ```js run -// replace a dash by a colon +// 把横线替换成冒号 alert('12-34-56'.replace("-", ":")) // 12:34-56 ``` -When the first argument of `replace` is a string, it only looks for the first match. +当 `replace` 的第一个参数是字符串时,它只会查找第一个匹配项。 -To find all dashes, we need to use not the string `"-"`, but a regexp `pattern:/-/g`, with an obligatory `g` flag: +如果要找到所有的横线,我们不能使用字符串 `"-"`,而是 regexp `pattern:/-/g`,带上 `g` 修饰符。 ```js run -// replace all dashes by a colon +// 用冒号替换所有的横线 alert( '12-34-56'.replace( *!*/-/g*/!*, ":" ) ) // 12:34:56 ``` -The second argument is a replacement string. +第二个参数是要替换的字符串。 -We can use special characters in it: +我们可以在里面使用特殊符号: -| Symbol | Inserts | +| 符号 | 插入 | |--------|--------| |`$$`|`"$"` | -|`$&`|the whole match| -|$`|a part of the string before the match| -|`$'`|a part of the string after the match| -|`$n`|if `n` is a 1-2 digit number, then it means the contents of n-th parentheses counting from left to right| +|`$&`|整个匹配项| +|$`|匹配项前面的字符串部分| +|`$'`|匹配项后面的字符串部分| +|`$n`|如果 `n` 是一个 1-2 位的数字,那么这表示从左到右数第 n 个括号的内容| -For instance let's use `$&` to replace all entries of `"John"` by `"Mr.John"`: +在下面的例子中,使用 `$&` 将所有的 `"John"` 替换成 `"Mr.John"`: ```js run let str = "John Doe, John Smith and John Bull."; -// for each John - replace it with Mr. and then John +// 对于每个 John — 替换成 Mr.John alert(str.replace(/John/g, 'Mr.$&')); // "Mr.John Doe, Mr.John Smith and Mr.John Bull."; ``` -Parentheses are very often used together with `$1`, `$2`, like this: +圆括号通常与 `$1`,`$2` 一起使用,就像下面的例子: ```js run let str = "John Smith"; @@ -171,36 +171,36 @@ let str = "John Smith"; alert(str.replace(/(John) (Smith)/, '$2, $1')) // Smith, John ``` -**For situations that require "smart" replacements, the second argument can be a function.** +**对于那些需要“智能”替换的场景,第二个参数可以是函数。** -It will be called for each match, and its result will be inserted as a replacement. +它会在每次匹配时被调用,并且其返回值会替换掉匹配项。 -For instance: +例如: ```js run let i = 0; -// replace each "ho" by the result of the function +// 将每个“ho”都替换成函数所返回的结果 alert("HO-Ho-ho".replace(/ho/gi, function() { return ++i; })); // 1-2-3 ``` -In the example above the function just returns the next number every time, but usually the result is based on the match. +在上面的示例中,函数每次只返回下一个数字,但通常结果是基于匹配的。 -The function is called with arguments `func(str, p1, p2, ..., pn, offset, s)`: +调用该函数 `func(str, p1, p2, ..., pn, offset, s)` 的参数是: -1. `str` -- the match, -2. `p1, p2, ..., pn` -- contents of parentheses (if there are any), -3. `offset` -- position of the match, -4. `s` -- the source string. +1. `str` — 匹配项, +2. `p1, p2, ..., pn` — 圆括号里的内容(如果有的话), +3. `offset` — 匹配项所在的位置, +4. `s` — 源字符串。 -If there are no parentheses in the regexp, then the function always has 3 arguments: `func(str, offset, s)`. +如果在 regexp 中没有圆括号,那么该函数总是有 3 个参数:`func(str, offset, s)`。 -Let's use it to show full information about matches: +下面的代码展示了匹配的所有信息: ```js run -// show and replace all matches +// 显示并且替换所有的匹配项 function replacer(str, offset, s) { alert(`Found ${str} at position ${offset} in string ${s}`); return str.toLowerCase(); @@ -215,7 +215,7 @@ alert( 'Result: ' + result ); // Result: ho-ho-ho // Found ho at position 6 in string HO-Ho-ho ``` -In the example below there are two parentheses, so `replacer` is called with 5 arguments: `str` is the full match, then parentheses, and then `offset` and `s`: +在下面的例子中,有两个圆括号,所以 `replacer` 有 5 个参数:`str` 是完全匹配项,然后是圆括号,然后是 `offset` 和 `s`: ```js run function replacer(str, name, surname, offset, s) { @@ -228,25 +228,25 @@ let str = "John Smith"; alert(str.replace(/(John) (Smith)/, replacer)) // Smith, John ``` -Using a function gives us the ultimate replacement power, because it gets all the information about the match, has access to outer variables and can do everything. +使用函数赋予了我们终极替换大招,因为这能获取所有的匹配信息,并且能够访问外部变量,可以做任何事情。 ## regexp.test(str) -Let's move on to the methods of `RegExp` class, that are callable on regexps themselves. +让我们继续研究 `RegExp` 类的方法,它们可以被 regexp 自身调用。 -The `test` method looks for any match and returns `true/false` whether he found it. +`test` 方法查找任何符合的匹配,无论是否找到,都会返回 `true/false`。 -So it's basically the same as `str.search(reg) != -1`, for instance: +所以这基本上和 `str.search(reg) != -1` 一样,例如: ```js run let str = "I love JavaScript"; -// these two tests do the same +// 这两条语句是一样的 alert( *!*/love/i*/!*.test(str) ); // true alert( str.search(*!*/love/i*/!*) != -1 ); // true ``` -An example with the negative answer: +结果是 false 的例子: ```js run let str = "Bla-bla-bla"; @@ -257,24 +257,24 @@ alert( str.search(*!*/love/i*/!*) != -1 ); // false ## regexp.exec(str) -We've already seen these searching methods: +我们已经见过这些搜索的方法: -- `search` -- looks for the position of the match, -- `match` -- if there's no `g` flag, returns the first match with parentheses, -- `match` -- if there's a `g` flag -- returns all matches, without separating parentheses. +- `search` — 查找匹配项所在的位置, +- `match` — 如果没有 `g` 修饰符,返回圆括号的第一个匹配项, +- `match` — 如果有 `g` 修饰符,返回所有匹配项,圆括号在此不生效。 -The `regexp.exec` method is a bit harder to use, but it allows to search all matches with parentheses and positions. +`regexp.exec` 方法有点难用,但是它允许搜索所有的匹配项,包括圆括号和位置。 -It behaves differently depending on whether the regexp has the `g` flag. +它的行为取决于 regexp 是否具有“g”修饰符。 -- If there's no `g`, then `regexp.exec(str)` returns the first match, exactly as `str.match(reg)`. -- If there's `g`, then `regexp.exec(str)` returns the first match and *remembers* the position after it in `regexp.lastIndex` property. The next call starts to search from `regexp.lastIndex` and returns the next match. If there are no more matches then `regexp.exec` returns `null` and `regexp.lastIndex` is set to `0`. +- 如果没有 `g`,那么 `regexp.exec(str)` 返回第一个匹配项,也就是 `str.match(reg)`。 +- 如果有 `g`,那么 `regexp.exec(str)` 返回第一个匹配项,然后在 `regexp.lastIndex` 里 **记住** 该匹配项结束的的位置。下一次调用从 `regexp.lastIndex` 开始搜索,并且返回下一个匹配项。如果再没有匹配项了,则 `regexp.exec` 返回 `null`,`regexp.lastIndex` 置为 `0`。 -As we can see, the method gives us nothing new if we use it without the `g` flag, because `str.match` does exactly the same. +正如我们所见的,如果不使用 `g` 修饰符,则与 `str.match` 没有什么区别。 -But the `g` flag allows to get all matches with their positions and parentheses groups. +但是使用 `g` 修饰符,就能够获取所有的匹配项,以及其位置和圆括号组的信息。 -Here's the example how subsequent `regexp.exec` calls return matches one by one: +下面的代码展示了 `regexp.exec` 是如何一个接一个进行调用的: ```js run let str = "A lot about JavaScript at https://javascript.info"; @@ -282,39 +282,39 @@ let str = "A lot about JavaScript at https://javascript.info"; let regexp = /JAVA(SCRIPT)/ig; *!* -// Look for the first match +// 查找第一个匹配项 */!* let matchOne = regexp.exec(str); alert( matchOne[0] ); // JavaScript alert( matchOne[1] ); // script -alert( matchOne.index ); // 12 (the position of the match) -alert( matchOne.input ); // the same as str +alert( matchOne.index ); // 12(匹配项所在的位置) +alert( matchOne.input ); // 和 str 一样 -alert( regexp.lastIndex ); // 22 (the position after the match) +alert( regexp.lastIndex ); // 22(匹配项结束的位置) *!* -// Look for the second match +// 查找第二个匹配项 */!* -let matchTwo = regexp.exec(str); // continue searching from regexp.lastIndex +let matchTwo = regexp.exec(str); // 继续从 regexp.lastIndex 开始搜索 alert( matchTwo[0] ); // javascript alert( matchTwo[1] ); // script -alert( matchTwo.index ); // 34 (the position of the match) -alert( matchTwo.input ); // the same as str +alert( matchTwo.index ); // 34(匹配项所在的位置) +alert( matchTwo.input ); // 和 str 一样 -alert( regexp.lastIndex ); // 44 (the position after the match) +alert( regexp.lastIndex ); // 44(匹配项结束的位置) *!* -// Look for the third match +// 查找第三个匹配项 */!* -let matchThree = regexp.exec(str); // continue searching from regexp.lastIndex -alert( matchThree ); // null (no match) +let matchThree = regexp.exec(str); // 继续从 regexp.lastIndex 开始搜索 +alert( matchThree ); // null(没有匹配项) -alert( regexp.lastIndex ); // 0 (reset) +alert( regexp.lastIndex ); // 0(重置) ``` -As we can see, each `regexp.exec` call returns the match in a "full format": as an array with parentheses, `index` and `input` properties. +可见,每个 `regexp.exec` 调用都以”完整的格式“返回匹配项:一个由圆括号、`index` 和 `input` 属性组成的数组。 -The main use case for `regexp.exec` is to find all matches in a loop: +`regexp.exec` 的主要用例就是在循环中查找所有的匹配: ```js run let str = 'A lot about JavaScript at https://javascript.info'; @@ -328,10 +328,10 @@ while (result = regexp.exec(str)) { } ``` -The loop continues until `regexp.exec` returns `null` that means "no more matches". +循环直到 `regexp.exec` 返回 `null` 时结束,也就意味着“没有更多的匹配项了”。 -````smart header="Search from the given position" -We can force `regexp.exec` to start searching from the given position by setting `lastIndex` manually: +````smart header="从指定位置开始搜索" +我们可以强制 `regexp.exec` 从给定的位置开始搜索,只需要手动设置 `lastIndex`: ```js run let str = 'A lot about JavaScript at https://javascript.info'; @@ -339,69 +339,69 @@ let str = 'A lot about JavaScript at https://javascript.info'; let regexp = /javascript/ig; regexp.lastIndex = 30; -alert( regexp.exec(str).index ); // 34, the search starts from the 30th position +alert( regexp.exec(str).index ); // 34,搜索从位置 30 开始 ``` ```` -## The "y" flag [#y-flag] +## “y”修饰符 [#y-flag] -The `y` flag means that the search should find a match exactly at the position specified by the property `regexp.lastIndex` and only there. +`y` 修饰符意味着搜索应该并且只能在属性 `regexp.lastIndex` 指定的位置查找匹配项。 -In other words, normally the search is made in the whole string: `pattern:/javascript/` looks for "javascript" everywhere in the string. +也就是说,通常搜索是在整个字符串里搜索字符串 `pattern:/javascript/` 的。 -But when a regexp has the `y` flag, then it only looks for the match at the position specified in `regexp.lastIndex` (`0` by default). +但是当有了 `y` 修饰符,则只会在 `regexp.lastIndex`(默认是 `0`)指定的位置开始查找。 -For instance: +例如: ```js run let str = "I love JavaScript!"; let reg = /javascript/iy; -alert( reg.lastIndex ); // 0 (default) -alert( str.match(reg) ); // null, not found at position 0 +alert( reg.lastIndex ); // 0(默认) +alert( str.match(reg) ); // null, 没有在位置 0 上找到匹配项 reg.lastIndex = 7; -alert( str.match(reg) ); // JavaScript (right, that word starts at position 7) +alert( str.match(reg) ); // JavaScript(搜索正确,该单词确实在位置 7) -// for any other reg.lastIndex the result is null +// 对于其它 reg.lastIndex,结果都为 null ``` -The regexp `pattern:/javascript/iy` can only be found if we set `reg.lastIndex=7`, because due to `y` flag the engine only tries to find it in the single place within a string -- from the `reg.lastIndex` position. +regexp `pattern:/javascript/iy` 只有在我们设置 `reg.lastIndex=7` 的时候被找到,因为由于 `y` 修饰符,引擎只会尝试在 `reg.lastIndex` 这个特定的位置开始查找。 -So, what's the point? Where do we apply that? +所以,这样做有何意义?我们在什么情况下会用到呢? -The reason is performance. +答案就是性能。 -The `y` flag works great for parsers -- programs that need to "read" the text and build in-memory syntax structure or perform actions from it. For that we move along the text and apply regular expressions to see what we have next: a string? A number? Something else? +`y` 修饰符非常适合解析器 — 一种需要“读取”文本、构建内存语法结构或者从中执行操作的程序。为此,我们沿着文本移动,应用正则表达式,来看下一个是字符串、数字还是其它。 -The `y` flag allows to apply a regular expression (or many of them one-by-one) exactly at the given position and when we understand what's there, we can move on -- step by step examining the text. +`y` 修饰符在给定位置应用一个正则表达式(或者会有很多,逐个进行),当我们理解了其中的内容后,就可以继续一步步检查文本。 -Without the flag the regexp engine always searches till the end of the text, that takes time, especially if the text is large. So our parser would be very slow. The `y` flag is exactly the right thing here. +在没有该修饰符的情况下,引擎总是会检查到文本的末尾,这需要花费时间,尤其是当文本很大的时候,解析器将会很慢。`y` 修饰符在这里使用则恰到好处。 -## Summary, recipes +## 总结,方法 -Methods become much easier to understand if we separate them by their use in real-life tasks. +如果我们按照这些方法在实际任务中的用途进行划分,则会更容易理解。 -To search for the first match only: -: - Find the position of the first match -- `str.search(reg)`. -- Find the full match -- `str.match(reg)`. -- Check if there's a match -- `regexp.test(str)`. -- Find the match from the given position -- `regexp.exec(str)`, set `regexp.lastIndex` to position. +只查找第一个匹配项的: +: - 找到第一个匹配项的位置 — `str.search(reg)`。 +- 找到完全匹配 — `str.match(reg)`。 +- 检查是否有符合条件的匹配 — `regexp.test(str)`。 +- 从指定位置查找匹配 — `regexp.exec(str)`,设置 `regexp.lastIndex` 位置。 -To search for all matches: -: - An array of matches -- `str.match(reg)`, the regexp with `g` flag. -- Get all matches with full information about each one -- `regexp.exec(str)` with `g` flag in the loop. +查找全匹配: +: - 由匹配项组成的数组 — `str.match(reg)`, 使用 `g` 修饰符。 +- 获取所有匹配项的完整信息 — `regexp.exec(str)`,在循环中使用 `g` 修饰符。 -To search and replace: -: - Replace with another string or a function result -- `str.replace(reg, str|func)` +搜索然后替换: +: - 替换成另一个字符串或者函数返回的结果 — `str.replace(reg, str|func)` -To split the string: +拆分字符串: : - `str.split(str|reg)` -We also covered two flags: +我们还讨论了两个修饰符: -- The `g` flag to find all matches (global search), -- The `y` flag to search at exactly the given position inside the text. +- `g` 修饰符查找所有的匹配项(全局搜索), +- `y` 修饰符在文本中的指定位置查找。 -Now we know the methods and can use regular expressions. But we need to learn their syntax, so let's move on. +现在我们知道了这些方法,并且可以使用正则表达式了。但是我们需要学习它们的语法,所以我们继续下一章节。