diff --git a/09_regexp.md b/09_regexp.md index f8f8291..0c22f69 100644 --- a/09_regexp.md +++ b/09_regexp.md @@ -1,9 +1,10 @@ -# Regular Expressions +# Expressões Regulares {{quote {author: "Jamie Zawinski", chapter: true} -Some people, when confronted with a problem, think 'I know, I'll use -regular expressions.' Now they have two problems. +> "Algumas pessoas, quando confrontadas com um problema, pensam "Eu sei, terei que usar expressões regulares." Agora elas têm dois problemas. +> +> — Jamie Zawinski quote}} @@ -13,9 +14,9 @@ quote}} {{quote {author: "Master Yuan-Ma", title: "The Book of Programming", chapter: true} -Yuan-Ma said, 'When you cut against the grain of the wood, much -strength is needed. When you program against the grain of the problem, -much code is needed.' +> "Yuan-Ma disse, 'Quando você serra contra o sentido da madeira, muita força será necessária. Quando você programa contra o sentido do problema, muito código será necessário' +> +> — Mestre Yuan-Ma, The Book of Programming quote}} @@ -25,75 +26,50 @@ if}} {{index evolution, adoption, integration}} -Programming ((tool))s and techniques survive and spread in a chaotic, -evolutionary way. It's not always the pretty or brilliant ones that -win but rather the ones that function well enough within the right -niche or that happen to be integrated with another successful piece of -technology. +A maneira como técnicas e convenções de programação sobrevivem e se disseminam, ocorrem de um modo caótico, evolucionário. Não é comum que a mais agradável e brilhante vença, mas sim aquelas que funcionam bem com o nicho ou as que aparentam ser integradas com outra tecnologia de sucesso. {{index "domain-specific language"}} -In this chapter, I will discuss one such tool, _((regular -expression))s_. Regular expressions are a way to describe ((pattern))s -in string data. They form a small, separate language that is part of -JavaScript and many other languages and systems. +Neste capítulo, discutiremos uma dessas tecnologias, expressões regulares. Expressões regulares são um modo de descrever padrões nos dados de uma _string_. Eles formam uma pequena linguagem à parte, que inclui JavaScript e várias outras linguagens e sistemas. {{index [interface, design]}} -Regular expressions are both terribly awkward and extremely useful. -Their syntax is cryptic, and the programming interface JavaScript -provides for them is clumsy. But they are a powerful ((tool)) for -inspecting and processing strings. Properly understanding regular -expressions will make you a more effective programmer. +Expressões regulares são ao mesmo tempo, estranhas e extremamente úteis. Sua sintaxe é enigmática é a interface que o JavaScript oferece para elas é desajeitada. Mas elas são uma ferramenta poderosa utilizada para inspecionar e processar _strings_. A compreensão adequada das expressões regulares fará de você um programador mais eficaz. -## Creating a regular expression +--- + +## Criando uma Expressão Regular {{index ["regular expression", creation], "RegExp class", "literal expression", "slash character"}} -A regular expression is a type of object. It can be either constructed -with the `RegExp` constructor or written as a literal value by -enclosing a pattern in forward slash (`/`) characters. +Uma expressão regular é um tipo de objeto. Ele pode ser construído com o construtor _RegExp_ ou escrito como um valor literal, encapsulando o padrão com o caractere barra ('/'). -``` +```js let re1 = new RegExp("abc"); let re2 = /abc/; ``` -Both of those regular expression objects represent the same -((pattern)): an _a_ character followed by a _b_ followed by a _c_. +Ambos os objetos acima representam o mesmo padrão: um caractere `a` seguido de um caractere `b` e depois de um caractere `c`. {{index ["backslash character", "in regular expressions"], "RegExp class"}} -When using the `RegExp` constructor, the pattern is written as a -normal string, so the usual rules apply for backslashes. +Ao usarmos o construtor `RegExp`, o padrão é escrito como uma _string_ normal, de modo que as regras normais se aplicam para barras invertidas. {{index ["regular expression", escaping], [escaping, "in regexps"], "slash character"}} -The second notation, where the pattern appears between slash -characters, treats backslashes somewhat differently. First, since a -forward slash ends the pattern, we need to put a backslash before any -forward slash that we want to be _part_ of the pattern. In addition, -backslashes that aren't part of special character codes (like `\n`) -will be _preserved_, rather than ignored as they are in strings, and -change the meaning of the pattern. Some characters, such as question -marks and plus signs, have special meanings in regular expressions and -must be preceded by a backslash if they are meant to represent the -character itself. +A segunda notação, onde o padrão está entre barras, trata as barras invertidas de maneira um pouco diferente. Primeiro, como uma barra encerra o padrão, é necessário colocarmos uma barra invertida antes de inserirmos qualquer barra que queremos que faça parte do padrão. Além disso, as barras invertidas que não pertencem a códigos de caracteres especiais (como `\n`) serão preservadas ao invés de serem ignoradas, pois fazem parte de _strings_ e alteram o significado do padrão. Alguns caracteres, como sinais de interrogação (`?`) e sinais de soma (`+`), possuem um significado especial em expressões regulares e devem ser precedidos por barras invertidas para representarem o próprio caractere, e não o comando de expressão regular. -``` +```js let eighteenPlus = /eighteen\+/; ``` -## Testing for matches +## Teste de correspondências {{index matching, "test method", ["regular expression", methods]}} -Regular expression objects have a number of methods. The simplest one -is `test`. If you pass it a string, it will return a ((Boolean)) -telling you whether the string contains a match of the pattern in the -expression. +Expressões regulares possuem vários métodos. O mais simples é o `test`. Se você o passa como uma _string_, ele retorna um booleano que informa se a _string_ mantém uma correspondência do padrão na expressão. -``` +```js console.log(/abc/.test("abcde")); // → true console.log(/abc/.test("abxde")); @@ -102,26 +78,19 @@ console.log(/abc/.test("abxde")); {{index pattern}} -A ((regular expression)) consisting of only nonspecial characters -simply represents that sequence of characters. If _abc_ occurs -anywhere in the string we are testing against (not just at the start), -`test` will return `true`. +Uma ((expressão regular)) que contenha apenas caracteres simples, representa essa mesma sequência de caracteres. Se "abc" existe em qualquer lugar (não apenas no início), `test` retornará verdadeiro. -## Sets of characters +## Encontrando um conjunto de caracteres {{index "regular expression", "indexOf method"}} -Finding out whether a string contains _abc_ could just as well be done -with a call to `indexOf`. Regular expressions allow us to express more -complicated ((pattern))s. +Saber quando uma _string_ contém "abc" pode muito bem ser feito usando a função `indexOf`. A diferença das expressões regulares é que elas nos permite usar padrões mais complexos. -Say we want to match any ((number)). In a regular expression, putting -a ((set)) of characters between square brackets makes that part of the -expression match any of the characters between the brackets. +Digamos que queremos encontrar qualquer número. Em uma expressão regular, colocar um conjunto de caracteres entre colchetes (`[]`) faz com que a expressão encontre qualquer dos caracteres dentro dos colchetes. -Both of the following expressions match all strings that contain a ((digit)): +Ambas as expressões abaixo encontram todas as _strings_ que contem um dígito numérico. -``` +```js console.log(/[0123456789]/.test("in 1992")); // → true console.log(/[0-9]/.test("in 1992")); @@ -130,34 +99,27 @@ console.log(/[0-9]/.test("in 1992")); {{index "hyphen character"}} -Within square brackets, a hyphen (`-`) between two characters can be -used to indicate a ((range)) of characters, where the ordering is -determined by the character's ((Unicode)) number. Characters 0 to 9 -sit right next to each other in this ordering (codes 48 to 57), so -`[0-9]` covers all of them and matches any ((digit)). +Dentro de colchetes, um hífen (`-`) entre dois caracteres pode ser usado para indicar um conjunto de caracteres, onde a ordem é determinada pelo número _Unicode_ do caractere. Os caracteres de `0` a `9` contém todos os dígitos (códigos 48 a 57), então `[0-9]` e encontra qualquer dígito. {{index [whitespace, matching], "alphanumeric character", "period character"}} -A number of common character groups have their own -built-in shortcuts. Digits are one of them: `\d` means the same thing -as `[0-9]`. +Existem alguns grupos de caracteres de uso comum, que já possuem atalhos inclusos. Dígitos são um deles: (`\d`), que possui o mesmo significado que `[0-9]`. {{index "newline character", [whitespace, matching]}} {{table {cols: [1, 5]}}} -| `\d` | Any ((digit)) character -| `\w` | An alphanumeric character ("((word character))") -| `\s` | Any whitespace character (space, tab, newline, and similar) -| `\D` | A character that is _not_ a digit -| `\W` | A nonalphanumeric character -| `\S` | A nonwhitespace character -| `.` | Any character except for newline + - \d caracteres numéricos + - \w caracteres alfanuméricos ("letras") + - \s espaços em branco (espaço, tabs, quebras de linha e similares) + - \D caracteres que não são dígitos + - \W caracteres não alfanuméricos + - \S caracteres que não representam espaços + - . (ponto) todos os caracteres, exceto espaços -So you could match a ((date)) and ((time)) format like 01-30-2003 -15:20 with the following expression: +Então você pode registrar um formato de data e hora como `30/01/2003 15:20` com a seguinte expressão: -``` +```js let dateTime = /\d\d-\d\d-\d\d\d\d \d\d:\d\d/; console.log(dateTime.test("01-30-2003 15:20")); // → true @@ -167,25 +129,17 @@ console.log(dateTime.test("30-jan-2003 15:20")); {{index ["backslash character", "in regular expressions"]}} -That looks completely awful, doesn't it? Half of it is backslashes, -producing a background noise that makes it hard to spot the actual -((pattern)) expressed. We'll see a slightly improved version of this -expression [later](regexp#date_regexp_counted). +Parece confuso, certo? Muitas barras invertidas sujando a expressão e dificultando compreender qual é o padrão procurado. Veremos mais a frente uma versão melhorada desta expressão. {{index [escaping, "in regexps"], "regular expression", set}} -These backslash codes can also be used inside ((square brackets)). For -example, `[\d.]` means any digit or a period character. But the period -itself, between square brackets, loses its special meaning. The same -goes for other special characters, such as `+`. +Estes marcadores de categoria também podem ser usados dentro de colchetes, então `[\d.]` significa qualquer dígito ou caractere de ponto final. Mas o próprio ponto final, entre colchetes, perde seu significado especial. O mesmo vale para outros caracteres especiais, como `+`. {{index "square brackets", inversion, "caret character"}} -To _invert_ a set of characters—that is, to express that you want to -match any character _except_ the ones in the set—you can write a caret -(`^`) character after the opening bracket. +Para "inverter" um conjunto de caracteres e buscar tudo menos o que você escreveu no padrão, você pode colocar um acento circunflexo (`^`) após abrir colchetes. -``` +```js let notBinary = /[^01]/; console.log(notBinary.test("1100100010100110")); // → false @@ -193,20 +147,17 @@ console.log(notBinary.test("1100100010200110")); // → true ``` -## Repeating parts of a pattern +## Partes repetidas em um padrão {{index ["regular expression", repetition]}} -We now know how to match a single digit. What if we want to match a -whole number—a ((sequence)) of one or more ((digit))s? +Agora nós já sabemos como encontrar um dígito, mas e se o que queremos é encontrar um número, uma sequência de um ou mais dígitos? -{{index "plus character", repetition, "+ operator"}} +{{index "plus character", repetition, `+ operator`}} -When you put a plus sign (`+`) after something in a regular -expression, it indicates that the element may be repeated more than -once. Thus, `/\d+/` matches one or more digit characters. +Quando colocamos um sinal de mais (`+`) depois de algo em uma expressão regular, indicamos que pode existir mais de um. Então `/\d+/` encontra um ou mais dígitos. -``` +```js console.log(/'\d+'/.test("'123'")); // → true console.log(/'\d+'/.test("''")); @@ -219,19 +170,13 @@ console.log(/'\d*'/.test("''")); {{index "* operator", asterisk}} -The star (`*`) has a similar meaning but also allows the pattern to -match zero times. Something with a star after it never prevents a -pattern from matching—it'll just match zero instances if it can't find -any suitable text to match. +O asterisco (`*`) tem um significado similar, mas também permite não encontrar o padrão. Então, algo colocado com um asterisco depois dele, não impede um padrão de ser achado, ele apenas retornará zero resultados se não conseguir encontrar algum texto adequado. {{index "British English", "American English", "question mark"}} -A question mark makes a part of a pattern _((optional))_, meaning it -may occur zero times or one time. In the following example, the _u_ -character is allowed to occur, but the pattern also matches when it is -missing. +Uma interrogação (`?`) define uma parte do padrão de busca como "opcional", o que significa que ele pode ocorrer zero vezes ou apenas uma vez. No exemplo a seguir, é permitido que ocorra o caractere `u`, mas o padrão também é encontrado quando ele está ausente. -``` +```js let neighbor = /neighbou?r/; console.log(neighbor.test("neighbour")); // → true @@ -241,38 +186,27 @@ console.log(neighbor.test("neighbor")); {{index repetition, [braces, "in regular expression"]}} -To indicate that a pattern should occur a precise number of times, use -braces. Putting `{4}` after an element, for example, requires it -to occur exactly four times. It is also possible to specify a -((range)) this way: `{2,4}` means the element must occur at least -twice and at most four times. +Para permitir que um padrão ocorra um número definido de vezes, use chaves (`{}`). Colocando `{4}` depois de um elemento do padrão, requer que ele ocorra exatamente 4 vezes. Da mesma maneira, `{2,4}` é utilizado para definir que ele deve aparecer no mínimo 2 vezes e no máximo 4. {{id date_regexp_counted}} -Here is another version of the ((date)) and ((time)) pattern that -allows both single- and double-((digit)) days, months, and hours. It -is also slightly easier to decipher. +Aqui está outra versão do padrão de data e hora que permite dias, meses e horas com um ou mais dígitos. Também são mais legíveis: -``` +```js let dateTime = /\d{1,2}-\d{1,2}-\d{4} \d{1,2}:\d{2}/; console.log(dateTime.test("1-30-2003 8:45")); // → true ``` -You can also specify open-ended ((range))s when using braces -by omitting the number after the comma. So, `{5,}` means five or more -times. +Também é possível deixar em aberto o número mínimo ou máximo de ocorrências, omitindo o número após a vírgula. Então `{5,}` significa que deve ocorrer cinco ou mais vezes. -## Grouping subexpressions +## Agrupando subexpressões {{index ["regular expression", grouping], grouping, [parentheses, "in regular expressions"]}} -To use an operator like `*` or `+` on more than one element at a time, -you have to use parentheses. A part of a regular expression that -is enclosed in parentheses counts as a single element as far as the -operators following it are concerned. +Para usar um operador como `*` ou `+` em mais de um caractere por vez, é necessário o uso de parênteses. Um pedaço de uma expressão regular que é delimitado por parênteses conta como uma única unidade, assim como os operadores aplicados a esse pedaço delimitado. -``` +```js let cartoonCrying = /boo+(hoo+)+/i; console.log(cartoonCrying.test("Boohoooohoohooo")); // → true @@ -280,27 +214,19 @@ console.log(cartoonCrying.test("Boohoooohoohooo")); {{index crying}} -The first and second `+` characters apply only to the second _o_ in -_boo_ and _hoo_, respectively. The third `+` applies to the whole -group `(hoo+)`, matching one or more sequences like that. +O primeiro e segundo caractere `+` aplicam-se apenas ao segundo `o` em `boo hoo`, respectivamente. O terceiro `+` se aplica a todo grupo (`hoo+`), combinando uma ou mais sequências como essa. {{index "case sensitivity", capitalization, ["regular expression", flags]}} -The `i` at the end of the expression in the example makes this regular -expression case insensitive, allowing it to match the uppercase _B_ in -the input string, even though the pattern is itself all lowercase. +O "i" no final da expressão do exemplo acima faz com que a expressão regular seja _case-insensitive_, permitindo-a encontrar a letra maiúscula `B` na _string_ dada, mesmo que a descrição do padrão tenha sido feita em letras minúsculas. -## Matches and groups +## Resultados e grupos {{index ["regular expression", grouping], "exec method", [array, "RegExp match"]}} -The `test` method is the absolute simplest way to match a regular -expression. It tells you only whether it matched and nothing else. -Regular expressions also have an `exec` (execute) method that will -return `null` if no match was found and return an object with -information about the match otherwise. +O método `test` é a maneira mais simples de encontrar correspondências de uma expressão regular. Ela apenas informa se foi encontrado algo e nada mais. Expressões regulares também possuem o método `exec` (executar), que irá retornar `null` quando nenhum resultado for encontrado, e um objeto com informações se encontrar. -``` +```js let match = /\d+/.exec("one two 100"); console.log(match); // → ["100"] @@ -310,31 +236,22 @@ console.log(match.index); {{index "index property", [string, indexing]}} -An object returned from `exec` has an `index` property that tells us -_where_ in the string the successful match begins. Other than that, -the object looks like (and in fact is) an array of strings, whose -first element is the string that was matched. In the previous example, -this is the sequence of ((digit))s that we were looking for. +Um objeto retornado pelo método _exec_ possui um index de propriedades que informa aonde na _string_ o resultado encontrado se inicia. Além disso, o objeto parece (e de fato é) um _array_ de _strings_, cujo primeiro elemento é a _string_ que foi encontrada. No exemplo anterior, esta é a sequência de dígitos que estávamos procurando. {{index [string, methods], "match method"}} -String values have a `match` method that behaves similarly. +Valores _string_ possuem um método que se comporta de maneira semelhante. -``` +```js console.log("one two 100".match(/\d+/)); // → ["100"] ``` {{index grouping, "capture group", "exec method"}} -When the regular expression contains subexpressions grouped with -parentheses, the text that matched those groups will also show up in -the array. The whole match is always the first element. The next -element is the part matched by the first group (the one whose opening -parenthesis comes first in the expression), then the second group, and -so on. +Quando uma expressão regular contém expressões agrupadas entre parênteses, o texto que corresponde a esses grupos também aparece no _array_. O primeiro elemento sempre é todo o resultado, seguido pelo resultado do primeiro grupo entre parênteses, depois o segundo grupo e assim em diante. -``` +```js let quotedText = /'([^']*)'/; console.log(quotedText.exec("she said 'hello'")); // → ["'hello'", "hello"] @@ -342,12 +259,9 @@ console.log(quotedText.exec("she said 'hello'")); {{index "capture group"}} -When a group does not end up being matched at all (for example, when -followed by a question mark), its position in the output array will -hold `undefined`. Similarly, when a group is matched multiple times, -only the last match ends up in the array. +Quando um grupo não termina sendo achado (se por exemplo, possui um sinal de interrogação depois dele), seu valor no array de resultado será undefined. Do mesmo modo, quando um grupo é achado várias vezes, apenas o último resultado encontrado estará no array. -``` +```js console.log(/bad(ly)?/.exec("bad")); // → ["bad", undefined] console.log(/(\d)+/.exec("123")); @@ -356,33 +270,26 @@ console.log(/(\d)+/.exec("123")); {{index "exec method", ["regular expression", methods], extraction}} -Groups can be useful for extracting parts of a string. If we don't -just want to verify whether a string contains a ((date)) but also -extract it and construct an object that represents it, we can wrap -parentheses around the digit patterns and directly pick the date out -of the result of `exec`. +Grupos podem ser muito úteis para extrair partes de uma _string_. Por exemplo, podemos querer não apenas verificar quando uma _string_ contém uma data, mas também extraí-la, e construir um objeto que a representa. Se adicionarmos parênteses em volta do padrão de dígitos, poderemos selecionar a data no resultado da função `exec`. -But first we'll take a brief detour, in which we discuss the built-in way to -represent date and ((time)) values in JavaScript. +Mas antes, um pequeno desvio, na qual discutiremos a maneira integrada de representar os valores de data e hora em JavaScript. -## The Date class +## O tipo _Data_ {{index constructor, "Date class"}} -JavaScript has a standard class for representing ((date))s—or, rather, -points in ((time)). It is called `Date`. If you simply create a date -object using `new`, you get the current date and time. +O JavaScript possui uma classe padrão para representar datas, ou melhor, pontos no tempo. Ele é chamado `Date`. Se você simplesmente criar uma data usando `new`, terá a data e hora atual. -```{test: no} +```js console.log(new Date()); // → Mon Nov 13 2017 16:19:11 GMT+0100 (CET) ``` {{index "Date class"}} -You can also create an object for a specific time. +Também é possível criar um objeto para uma hora específica -``` +```js console.log(new Date(2009, 11, 9)); // → Wed Dec 09 2009 00:00:00 GMT+0100 (CET) console.log(new Date(2009, 11, 9, 12, 59, 59, 999)); @@ -391,22 +298,15 @@ console.log(new Date(2009, 11, 9, 12, 59, 59, 999)); {{index "zero-based counting", [interface, design]}} -JavaScript uses a convention where month numbers start at zero (so -December is 11), yet day numbers start at one. This is confusing and -silly. Be careful. +O JavaScript utiliza uma convenção onde a numeração dos meses se inicia em zero (então Dezembro é 11), mas os dias iniciam-se em um. É bem confuso e bobo, então, tenha cuidado. -The last four arguments (hours, minutes, seconds, and milliseconds) -are optional and taken to be zero when not given. +Os últimos quatro argumentos (horas, minutos, segundos e milissegundos) são opcionais, e assumem o valor de zero se não forem fornecidos. {{index "getTime method"}} -Timestamps are stored as the number of milliseconds since the start of -1970, in the UTC ((time zone)). This follows a convention set by -"((Unix time))", which was invented around that time. You can use -negative numbers for times before 1970. The `getTime` method on a date -object returns this number. It is big, as you can imagine. +Internamente, objetos do tipo data são armazenados como o número de milissegundos desde o início de 1970, no fuso horário UTC. Ele segue uma convenção definida pela "hora do _Unix_", que foi inventada nessa época. Você pode usar números negativos para tempos anteriores a 1970. Usar o método `getTime` em uma data retorna esse número, e ele é bem grande, como deve imaginar. -``` +```js console.log(new Date(2013, 11, 19).getTime()); // → 1387407600000 console.log(new Date(1387407600000)); @@ -415,28 +315,20 @@ console.log(new Date(1387407600000)); {{index "Date.now function", "Date class"}} -If you give the `Date` constructor a single argument, that argument is -treated as such a millisecond count. You can get the current -millisecond count by creating a new `Date` object and calling -`getTime` on it or by calling the `Date.now` function. +Quando fornecemos apenas um argumento ao construtor do `Date`, ele é tratado como se fosse um número de milissegundos. Você pode obter a contagem atual de milissegundos criando um novo objeto `Date` usando o método `getTime` ou chamando a função `Date.now`. {{index "getFullYear method", "getMonth method", "getDate method", "getHours method", "getMinutes method", "getSeconds method", "getYear method"}} -Date objects provide methods such as `getFullYear`, `getMonth`, -`getDate`, `getHours`, `getMinutes`, and `getSeconds` to extract their -components. Besides `getFullYear` there's also `getYear`, which gives -you the year minus 1900 (`98` or `119`) and is mostly useless. - {{index "capture group", "getDate method", [parentheses, "in regular expressions"]}} -Putting parentheses around the parts of the expression that we are -interested in, we can now create a date object from a string. +Objetos `Date` possuem métodos como `getFullYear`, `getMonth`, `getDate`, `getHours`, `getMinutes` e `getSeconds` para extrair seus componentes. Além de `getFullYear`, também há `getYear` que retorna o ano menos 1900 (98 ou 119) o que é quase inútil. -``` +Então agora, ao colocarmos parênteses em volta das partes que nos interessam, podemos facilmente extrair uma data de uma _string_. + +```js function getDate(string) { - let [_, month, day, year] = - /(\d{1,2})-(\d{1,2})-(\d{4})/.exec(string); - return new Date(year, month - 1, day); + let [_, month, day, year] = /(\d{1,2})-(\d{1,2})-(\d{4})/.exec(string); + return new Date(year, month - 1, day); } console.log(getDate("1-30-2003")); // → Thu Jan 30 2003 00:00:00 GMT+0100 (CET) @@ -444,37 +336,23 @@ console.log(getDate("1-30-2003")); {{index destructuring, "underscore character"}} -The `_` (underscore) binding is ignored and used only to skip the -full match element in the array returned by `exec`. +O `_` (underline) é ignorado e usado apenas para pular o elemento completo de correspondência no _array_ retornado por `exec`. -## Word and string boundaries +## Limites de palavra e _string_ {{index matching, ["regular expression", boundary]}} -Unfortunately, `getDate` will also happily extract the nonsensical -date 00-1-3000 from the string `"100-1-30000"`. A match may happen -anywhere in the string, so in this case, it'll just start at the -second character and end at the second-to-last character. +Infelizmente, a função `getDate` acima também irá extrair a data absurda `00-1-3000` da _string_ `100-1-30000`, um resultado pode acontecer em qualquer lugar da _string_ fornecida, então, nesse caso, vai encontrar no segundo caractere e terminar no penúltimo. {{index boundary, "caret character", "dollar sign"}} -If we want to enforce that the match must span the whole string, we -can add the markers `^` and `$`. The caret matches the start of the -input string, whereas the dollar sign matches the end. So, `/^\d+$/` -matches a string consisting entirely of one or more digits, `/^!/` -matches any string that starts with an exclamation mark, and `/x^/` -does not match any string (there cannot be an _x_ before the start of -the string). +Se quisermos nos assegurar que a busca seja em todo a _string_, podemos adicionar os marcadores `^` e `$`. O acento circunflexo corresponde ao início da _string_ fornecida, enquanto a sifrão corresponde ao final dela. Então `/^\d+$/` encontra apenas em uma _string_ feita de um ou mais dígitos, `/^!/` encontra qualquer _string_ que começa com sinal de exclamação e `/x^/` não corresponde a nenhuma _string_ (não pode haver um x antes do início da _string_). {{index "word boundary", "word character"}} -If, on the other hand, we just want to make sure the date starts and -ends on a word boundary, we can use the marker `\b`. A word boundary -can be the start or end of the string or any point in the string that -has a word character (as in `\w`) on one side and a nonword character -on the other. +Se, por outro lado, queremos ter certeza que a data inicia e termina no limite da palavra, usamos o marcador `\b`. Um limite de palavra pode ser no início ou fim de uma _string_ ou qualquer ponto nela em que tenha um caractere de palavra de um lado e um caractere que não seja uma palavra de outro (como em `\w`). -``` +```js console.log(/cat/.test("concatenate")); // → true console.log(/\bcat\b/.test("concatenate")); @@ -483,24 +361,17 @@ console.log(/\bcat\b/.test("concatenate")); {{index matching}} -Note that a boundary marker doesn't match an actual character. It just -enforces that the regular expression matches only when a certain -condition holds at the place where it appears in the pattern. +Note que esses marcadores de limite não cobrem nenhum caractere real, eles apenas asseguram que a expressão regular corresponda apenas quando uma certa condição for mantida no lugar onde ele aparece no padrão. -## Choice patterns +## Padrões de escolha {{index branching, ["regular expression", alternatives], "farm example"}} -Say we want to know whether a piece of text contains not only a number -but a number followed by one of the words _pig_, _cow_, or _chicken_, -or any of their plural forms. +Digamos que queremos saber se um pedaço do texto contém não apenas um número, mas um número seguido por uma das palavras "porco", "vaca", "galinha" ou seus plurais também. -We could write three regular expressions and test them in turn, but -there is a nicer way. The ((pipe character)) (`|`) denotes a -((choice)) between the pattern to its left and the pattern to its -right. So I can say this: +Podemos escrever três expressões regulares, e testar cada uma, mas existe uma maneira mais simples. O caractere pipe (`|`) indica uma opção entre o padrão à esquerda ou a direita. Então podemos fazer: -``` +```js let animalCount = /\b\d+ (pig|cow|chicken)s?\b/; console.log(animalCount.test("15 pigs")); // → true @@ -510,157 +381,83 @@ console.log(animalCount.test("15 pigchickens")); {{index [parentheses, "in regular expressions"]}} -Parentheses can be used to limit the part of the pattern that the pipe -operator applies to, and you can put multiple such operators next to -each other to express a choice between more than two alternatives. +Parênteses podem ser usados para limitar a que parte do padrão que o pipe (`|`) se aplica, e você pode colocar vários desses operadores lado a lado para expressar uma escolha entre mais de dois padrões. -## The mechanics of matching +## O mecanismo de correspondência {{index ["regular expression", matching], [matching, algorithm], "search problem"}} -Conceptually, when you use `exec` or `test`, the regular expression -engine looks for a match in your string by trying to match the -expression first from the start of the string, then from the second -character, and so on, until it finds a match or reaches the end of the -string. It'll either return the first match that can be found or fail -to find any match at all. +Conceitualmente, quando usamos `exec` ou `test`, o mecanismo de expressão regular busca uma correspondência em sua _string_, tentando corresponder à expressão do início da _string_ primeiro, depois do segundo caractere e assim por diante, até encontrar uma correspondência ou chegar ao fim da _string_. Ele retornará a primeira correspondência que pode ser encontrada ou não encontrará nenhuma correspondência. {{index ["regular expression", matching], [matching, algorithm]}} -To do the actual matching, the engine treats a regular expression -something like a ((flow diagram)). This is the diagram for the -livestock expression in the previous example: +Para fazer a correspondência atual, o mecanismo trata a expressão regular como um diagrama de fluxo. Este é o diagrama para a expressão do conjunto de animais do exemplo anterior: -{{figure {url: "img/re_pigchickens.svg", alt: "Visualization of /\\b\\d+ (pig|cow|chicken)s?\\b/"}}} +{{figure {url: "img/re_pigchickens.svg", alt: "Visualization of /\b\d+ (pig|cow|chicken)s?\b/"}}} {{index traversal}} -Our expression matches if we can find a path from the left side of the -diagram to the right side. We keep a current position in the string, -and every time we move through a box, we verify that the part of the -string after our current position matches that box. - -So if we try to match `"the 3 pigs"` from position 4, our progress -through the flow chart would look like this: - - - At position 4, there is a word ((boundary)), so we can move past - the first box. +Uma _string_ corresponde à expressão se um caminho do início (esquerda) até o final (direita) do diagrama puder ser encontrado, com uma posição inicial e final correspondente, de modo que cada vez que passar em uma caixa, verificamos que a posição atual na sequência corresponde ao elemento descrito nela, e, para os elementos que correspondem caracteres reais (menos os limites de palavra), continue no fluxo das caixas. - - Still at position 4, we find a digit, so we can also move past the - second box. +Portanto, se tentarmos combinar `the 3 pigs` da posição 4, nosso progresso através do fluxograma ficaria assim: - - At position 5, one path loops back to before the second (digit) - box, while the other moves forward through the box that holds a - single space character. There is a space here, not a digit, so we - must take the second path. - - - We are now at position 6 (the start of _pigs_) and at the three-way - branch in the diagram. We don't see _cow_ or _chicken_ here, but we - do see _pig_, so we take that branch. - - - At position 9, after the three-way branch, one path skips the _s_ - box and goes straight to the final word boundary, while the other - path matches an _s_. There is an _s_ character here, not a word - boundary, so we go through the _s_ box. - - - We're at position 10 (the end of the string) and can match only a - word ((boundary)). The end of a string counts as a word boundary, - so we go through the last box and have successfully matched this - string. +- Na posição 4, existe um limite de palavra, então passamos a primeira caixa; +- Ainda na posição 4, encontramos um dígito, então também podemos passar a segunda caixa; +- Na posição 5, poderíamos voltar para antes da segunda caixa (dígitos), ou avançar através da caixa que contém um único caractere de espaço. Há um espaço aqui, não um dígito, por isso escolhemos o segundo caminho; +- Estamos agora na posição 6 (o início de `pigs`) e na divisão entre três caminhos do diagrama. Nós não temos `cow` ou `chicken` aqui, mas nós temos `pig`, por isso tomamos esse caminho; +- Na posição 9, depois da divisão em três caminhos, poderíamos também ignorar o "s" e ir direto para o limite da palavra, ou achar o "s" primeiro. Existe um "s", não um limite de palavra, então passamos a caixa "s"; +- Estamos na posição 10 (final da string) e só podemos achar um limite de palavra. O fim de uma _string_ conta como um limite de palavra, de modo que passamos através da última caixa e combinamos com sucesso a _string_. {{id backtracking}} -## Backtracking +## Retrocedendo {{index ["regular expression", backtracking], "binary number", "decimal number", "hexadecimal number", "flow diagram", [matching, algorithm], backtracking}} -The regular expression `/\b([01]+b|[\da-f]+h|\d+)\b/` matches either a -binary number followed by a _b_, a hexadecimal number (that is, base -16, with the letters _a_ to _f_ standing for the digits 10 to 15) -followed by an _h_, or a regular decimal number with no suffix -character. This is the corresponding diagram: +A expressão regular `/\b([01]+b|\d+|[\da-f]h)\b/` encontra um número binário seguido por um `b`, um número decimal, sem um caractere de sufixo, ou um número hexadecimal (de base 16, com as letras `a` a `f` para os algarismos de 10 a 15), seguido por um `h`. Este é o diagrama equivalente: -{{figure {url: "img/re_number.svg", alt: "Visualization of /\\b([01]+b|\\d+|[\\da-f]+h)\\b/"}}} +{{figure {url: "img/re_number.svg", alt: "Visualization of /\b([01]+b|\d+|[\da-f]+h)\b/"}}} {{index branching}} -When matching this expression, it will often happen that the top -(binary) branch is entered even though the input does not actually -contain a binary number. When matching the string `"103"`, for -example, it becomes clear only at the 3 that we are in the wrong -branch. The string _does_ match the expression, just not the branch we -are currently in. +Ao buscar esta expressão, muitas vezes o ramo superior será percorrido, mesmo que a entrada não contenha realmente um número binário. Quando busca a _string_ `103`, é apenas no `3` que torna-se claro que estamos no local errado. A _string_ é buscada não apenas no ramo que se está executando. {{index backtracking, "search problem"}} -So the matcher _backtracks_. When entering a branch, it remembers its -current position (in this case, at the start of the string, just past -the first boundary box in the diagram) so that it can go back and try -another branch if the current one does not work out. For the string -`"103"`, after encountering the 3 character, it will start trying the -branch for hexadecimal numbers, which fails again because there is no -_h_ after the number. So it tries the decimal number branch. This one -fits, and a match is reported after all. +É o que acontece se a expressão retroage. Quando entra em um ramo, ela guarda em que ponto aconteceu (nesse caso, no início da _string_, na primeira caixa do diagrama), então ela retrocede e tenta outro ramo do diagrama se o atual não encontra nenhum resultado. Então para a _string_ `103`, após encontrar o caractere `3`, ela tentará o segundo ramo do número decimal. E este, encontra um resultado. {{index [matching, algorithm]}} -The matcher stops as soon as it finds a full match. This means that if -multiple branches could potentially match a string, only the first one -(ordered by where the branches appear in the regular expression) is -used. - -Backtracking also happens for ((repetition)) operators like + and `*`. -If you match `/^.*x/` against `"abcxe"`, the `.*` part will first try -to consume the whole string. The engine will then realize that it -needs an _x_ to match the pattern. Since there is no _x_ past the end -of the string, the star operator tries to match one character less. -But the matcher doesn't find an _x_ after `abcx` either, so it -backtracks again, matching the star operator to just `abc`. _Now_ it -finds an _x_ where it needs it and reports a successful match from -positions 0 to 4. +Quando mais de um ramo encontra um resultado, o primeiro (na ordem em que foi escrito na expressão regular) será considerado. + +Retroceder acontece também, de maneiras diferentes, quando buscamos por operadores repetidos. Se buscarmos `/^._x/` em `abcxe`, a parte `._` tentará achar toda a _string_. Depois, tentará achar apenas o que for seguido de um `x`, e não existe um `x` no final da _string_. Então ela tentará achar desconsiderando um caractere, e outro, e outro. Quando acha o "x", sinaliza um resultado com sucesso, da posição 0 até 4. {{index performance, complexity}} -It is possible to write regular expressions that will do a _lot_ of -backtracking. This problem occurs when a pattern can match a piece of -input in many different ways. For example, if we get confused while -writing a binary-number regular expression, we might accidentally -write something like `/([01]+)+b/`. +É possível escrever expressões regulares que fazem muitos retrocessos. O Problema ocorre quando um padrão encontra um pedaço da _string_ de entrada de muitas maneiras. Por exemplo, se confundimos e escrevemos nossa expressão regular para achar binários e números assim `/([01]+)+b/`. {{figure {url: "img/re_slow.svg", alt: "Visualization of /([01]+)+b/",width: "6cm"}}} {{index "inner loop", [nesting, "in regexps"]}} -If that tries to match some long series of zeros and ones with no -trailing _b_ character, the matcher first goes through the inner -loop until it runs out of digits. Then it notices there is no _b_, so -it backtracks one position, goes through the outer loop once, and -gives up again, trying to backtrack out of the inner loop once more. -It will continue to try every possible route through these two loops. -This means the amount of work _doubles_ with each additional -character. For even just a few dozen characters, the resulting match -will take practically forever. +Ela tentará achar séries de zeros sem um `b` após elas, depois irá percorrer o circuito interno até passar por todos os dígitos. Quando perceber que não existe nenhum `b`, retorna uma posição e passa pelo caminho de fora mais uma vez, e de novo, retrocedendo até o circuito interno mais uma vez. Continuará tentando todas as rotas possíveis através destes dois _loops_, em todos os caracteres. Para _strings_ mais longas o resultado demorará praticamente para sempre. -## The replace method +## O método _replace_ {{index "replace method", "regular expression"}} -String values have a `replace` method that can be used to replace -part of the string with another string. +_Strings_ possuem o método `replace`, que pode ser usado para substituir partes da _string_ com outra _string_. -``` +```js console.log("papa".replace("p", "m")); // → mapa ``` {{index ["regular expression", flags], ["regular expression", global]}} -The first argument can also be a regular expression, in which case the -first match of the regular expression is replaced. When a `g` option -(for _global_) is added to the regular expression, _all_ matches in -the string will be replaced, not just the first. +O primeiro argumento também pode ser uma expressão regular; nesse caso, a primeira correspondência da expressão regular será substituída. Quando a opção `g` ("global") é adicionada à expressão regular, todas as correspondências na string serão substituídas, não apenas a primeira. -``` +```js console.log("Borobudur".replace(/[ou]/, "a")); // → Barobudur console.log("Borobudur".replace(/[ou]/g, "a")); @@ -669,88 +466,67 @@ console.log("Borobudur".replace(/[ou]/g, "a")); {{index [interface, design], argument}} -It would have been sensible if the choice between replacing one match -or all matches was made through an additional argument to `replace` or -by providing a different method, `replaceAll`. But for some -unfortunate reason, the choice relies on a property of the regular -expression instead. +Teria sido sensato se a escolha entre substituir uma correspondência ou todas as correspondências fosse feita por meio de um argumento adicional `replace`, ou fornecendo um método diferente `replaceAll`. Mas infelizmente a escolha depende de uma propriedade de expressão regular. {{index grouping, "capture group", "dollar sign", "replace method", ["regular expression", grouping]}} -The real power of using regular expressions with `replace` comes from -the fact that we can refer to matched groups in the replacement -string. For example, say we have a big string containing the names of -people, one name per line, in the format `Lastname, Firstname`. If we -want to swap these names and remove the comma to get a `Firstname -Lastname` format, we can use the following code: +A verdadeira utilidade do uso de expressões regulares com o método `replace` é a opção de fazer referências aos grupos combinados através da _string_. Por exemplo, se temos uma _string_ longa com nomes de pessoas, uma por linha, no formato "Lastname, Name" e queremos trocar essa ordem e remover a vírgula, para obter o formato "Name Lastname", podemos usar o seguinte código: -``` +```js console.log( - "Liskov, Barbara\nMcCarthy, John\nWadler, Philip" - .replace(/(\w+), (\w+)/g, "$2 $1")); + "Liskov, Barbara\nMcCarthy, John\nWadler, Philip".replace( + /(\w+), (\w+)/g, + "$2 $1" + ) +); // → Barbara Liskov // John McCarthy // Philip Wadler ``` -The `$1` and `$2` in the replacement string refer to the parenthesized -groups in the pattern. `$1` is replaced by the text that matched -against the first group, `$2` by the second, and so on, up to `$9`. -The whole match can be referred to with `$&`. +O `$1` e `$2` na _string_ de substituição referem-se as partes entre parênteses no padrão. `$1` será substituído pelo texto encontrado no primeiro grupo entre parênteses e `$2` pelo segundo, e assim em diante, até `$9`. A correspondência inteira pode ser referenciada com `$&`. {{index [function, "higher-order"], grouping, "capture group"}} -It is possible to pass a function—rather than a string—as the second -argument to `replace`. For each replacement, the function will be -called with the matched groups (as well as the whole match) as -arguments, and its return value will be inserted into the new string. +Também é possível passar uma função, em vez de uma _string_ no segundo argumento do método `replace`. Para cada substituição, a função será chamada com os grupos encontrados (bem como toda a correspondência) como argumentos, e o valor retornado pela função será inserido na nova _string_. -Here's a small example: +Aqui está um pequeno exemplo: -``` +```js let s = "the cia and fbi"; -console.log(s.replace(/\b(fbi|cia)\b/g, - str => str.toUpperCase())); +console.log(s.replace(/\b(fbi|cia)\b/g, (str) => str.toUpperCase())); // → the CIA and FBI ``` -Here's a more interesting one: +E outro exemplo mais interessante: -``` +```js let stock = "1 lemon, 2 cabbages, and 101 eggs"; function minusOne(match, amount, unit) { - amount = Number(amount) - 1; - if (amount == 1) { // only one left, remove the 's' - unit = unit.slice(0, unit.length - 1); - } else if (amount == 0) { - amount = "no"; - } - return amount + " " + unit; + amount = Number(amount) - 1; + if (amount == 1) + // only one left, remove the 's' + unit = unit.slice(0, unit.length - 1); + else if (amount == 0) amount = "no"; + return amount + " " + unit; } console.log(stock.replace(/(\d+) (\w+)/g, minusOne)); // → no lemon, 1 cabbage, and 100 eggs ``` -This takes a string, finds all occurrences of a number followed by an -alphanumeric word, and returns a string wherein every such occurrence -is decremented by one. +Ele pega a _string_, encontra todas as ocorrências de um número seguido por uma palavra alfanumérica e retorna uma nova _string_ onde em cada ocorrência é diminuído por um. -The `(\d+)` group ends up as the `amount` argument to the function, -and the `(\w+)` group gets bound to `unit`. The function converts -`amount` to a number—which always works since it matched `\d+`—and -makes some adjustments in case there is only one or zero left. +O grupo `\d+` finaliza o argumento _amount_ da função e o `\w+` limita a unidade. A função converte o valor em um número, desde que encontrado, `\d+` faz ajustes caso reste apenas um ou zero. -## Greed +## Quantificador / Greed {{index greed, "regular expression"}} -It is possible to use `replace` to write a function that removes all -((comment))s from a piece of JavaScript ((code)). Here is a first -attempt: +É possível usar o método `replace` para escrever uma função que remove todos os comentários de um pedaço de código JavaScript. Veja uma primeira tentativa: -```{test: wrap} +```js function stripComments(code) { - return code.replace(/\/\/.*|\/\*[^]*\*\//g, ""); + return code.replace(/\/\/.*|\/\*[^]*\*\//g, ""); } console.log(stripComments("1 + /* 2 */3")); // → 1 + 3 @@ -762,67 +538,37 @@ console.log(stripComments("1 /* a */+/* b */ 1")); {{index "period character", "slash character", "newline character", "empty set", "block comment", "line comment"}} -The part before the _or_ operator matches two slash characters -followed by any number of non-newline characters. The part for -multiline comments is more involved. We use `[^]` (any character that -is not in the empty set of characters) as a way to match any -character. We cannot just use a period here because block comments can -continue on a new line, and the period character does not match -newline characters. +A parte antes do operador ou corresponde a dois caracteres de barra seguidos por qualquer número de caracteres que não sejam de nova linha. A parte dos comentários em várias linhas é mais envolvente. Usamos `[^]` (qualquer caractere que não esteja no conjunto vazio de caracteres) como uma forma de corresponder a qualquer caractere. Não podemos simplesmente usar um ponto final aqui porque os comentários de bloco podem continuar em uma nova linha e o caractere de ponto final não corresponde a caracteres de uma nova linha. -But the output for the last line appears to have gone wrong. Why? +Mas o resultado da última linha parece errado. Por quê? {{index backtracking, greed, "regular expression"}} -The `[^]*` part of the expression, as I described in the section on -backtracking, will first match as much as it can. If that causes the -next part of the pattern to fail, the matcher moves back one character -and tries again from there. In the example, the matcher first tries to -match the whole rest of the string and then moves back from there. It -will find an occurrence of `*/` after going back four characters and -match that. This is not what we wanted—the intention was to match a -single comment, not to go all the way to the end of the code and find -the end of the last block comment. - -Because of this behavior, we say the repetition operators (`+`, `*`, -`?`, and `{}`) are _((greed))y_, meaning they match as much as they -can and backtrack from there. If you put a ((question mark)) after -them (`+?`, `*?`, `??`, `{}?`), they become nongreedy and start by -matching as little as possible, matching more only when the remaining -pattern does not fit the smaller match. - -And that is exactly what we want in this case. By having the star -match the smallest stretch of characters that brings us to a `*/`, we -consume one block comment and nothing more. - -```{test: wrap} +A parte `[^]*` da expressão, como foi escrita na seção "Retrocedendo", acima, encontrará primeiro tudo que puder e depois, se falhar, volta atrás e tenta mais uma vez a partir daí. Nesse caso, primeiro tentamos combinar no resto da _string_ e depois continuamos a partir daí. Ele encontrará uma ocorrência de `*/` depois volta quatro caracteres e acha um resultado. Isto não era o que desejávamos, queríamos um comentário de uma linha, para não ir até o final do código e encontrar o final do último comentário do bloco. + +Devido a esse comportamento, dizemos que os operadores de repetição em expressões regulares (`+`, `\*`, e `{}`) são gananciosos. Por padrão, eles quantificam, significa que eles encontram o que podem e retrocedem a partir daí. Se você colocar uma interrogação depois deles, eles se tornam _non_greedy_, e começam encontrando o menor grupo possível e o resto que não contenha o grupo menor. + +E é exatamente o que queremos nesse caso. Com o asterisco encontramos os grupos menores que tenham `\*/` no fechamento, encontramos um bloco de comentários e nada mais. + +```js function stripComments(code) { - return code.replace(/\/\/.*|\/\*[^]*?\*\//g, ""); + return code.replace(/\/\/.*|\/\*[\w\W]*?\*\//g, ""); } console.log(stripComments("1 /* a */+/* b */ 1")); // → 1 + 1 ``` -A lot of ((bug))s in ((regular expression)) programs can be traced to -unintentionally using a greedy operator where a nongreedy one would -work better. When using a ((repetition)) operator, consider the -nongreedy variant first. +Muitos bugs em programas de expressão regular podem ser rastreados até o uso não intencional de um operador ganancioso, onde um _non_greedy_ funcionaria melhor. Ao usar um operador de repetição, considere a variante _non_greedy_ primeiro. -## Dynamically creating RegExp objects +## Criando objetos RegExp dinamicamente {{index ["regular expression", creation], "underscore character", "RegExp class"}} -There are cases where you might not know the exact ((pattern)) you -need to match against when you are writing your code. Say you want to -look for the user's name in a piece of text and enclose it in -underscore characters to make it stand out. Since you will know the -name only once the program is actually running, you can't use the -slash-based notation. +Existem casos onde você pode não saber o padrão exato que você precisa quando escreve seu código. Digamos que você queira buscar o nome de um usuário em um pedaço de texto e colocá-lo entre caracteres `\_` para destacá-lo. O nome será fornecido apenas quando o programa estiver sendo executado, então não podemos usar a notação de barras para criar nosso padrão. -But you can build up a string and use the `RegExp` ((constructor)) on -that. Here's an example: +Mas podemos construir uma _string_ e usar o construtor _RegExp_ para isso. Por exemplo: -``` +```js let name = "harry"; let text = "Harry is a suspicious character."; let regexp = new RegExp("\\b(" + name + ")\\b", "gi"); @@ -832,22 +578,15 @@ console.log(text.replace(regexp, "_$1_")); {{index ["regular expression", flags], ["backslash character", "in regular expressions"]}} -When creating the `\b` ((boundary)) markers, we have to use two -backslashes because we are writing them in a normal string, not a -slash-enclosed regular expression. The second argument to the `RegExp` -constructor contains the options for the regular expression—in this -case, `"gi"` for global and case insensitive. +Ao criar os marcos de limite `\b`, usamos duas barras invertidas, porque estamos escrevendo-os em uma _string_ normal, não uma expressão regular com barras. O segundo argumento para o _RegExp_ construtor contém as opções com a expressão regular - neste caso, o `gi` para global não diferencia maiúsculas de minúsculas. -But what if the name is `"dea+hl[]rd"` because our user is a ((nerd))y -teenager? That would result in a nonsensical regular expression that -won't actually match the user's name. +Mas e se o nome for `dea+hl[]rd` porque o nosso usuário é um adolescente nerd? Isso irá gerar uma falsa expressão regular, por conter caracteres comando, que irá gerar um resultado estranho. {{index ["backslash character", "in regular expressions"], [escaping, "in regexps"], ["regular expression", escaping]}} -To work around this, we can add backslashes before any character that -has a special meaning. +Para contornar isso, adicionamos contrabarras antes de qualquer caractere que tenha um significado especial. -``` +```js let name = "dea+hl[]rd"; let text = "This dea+hl[]rd guy is super annoying."; let escaped = name.replace(/[\\[.+*?(){|^$]/g, "\\$&"); @@ -856,51 +595,36 @@ console.log(text.replace(regexp, "_$&_")); // → This _dea+hl[]rd_ guy is super annoying. ``` -## The search method +## O método _search_ {{index ["regular expression", methods], "indexOf method", "search method"}} -The `indexOf` method on strings cannot be called with a regular -expression. But there is another method, `search`, that does expect a -regular expression. Like `indexOf`, it returns the first index on -which the expression was found, or -1 when it wasn't found. +O método _indexOf_ em _strings_ não pode ser chamado com uma expressão regular. Mas existe um outro método, _search_, que espera como argumento uma expressão regular. Por exemplo, o _indexOf_ que retorna o índice do primeiro resultado encontrado ou `-1` se não encontra. -``` +```js console.log(" word".search(/\S/)); // → 2 console.log(" ".search(/\S/)); // → -1 ``` -Unfortunately, there is no way to indicate that the match should start -at a given offset (like we can with the second argument to `indexOf`), -which would often be useful. +Infelizmente, não existe um modo de indicar onde a busca deve começar, com um índice (como o segundo argumento de `indexOf`), o que seria muito útil. -## The lastIndex property +## A propriedade _lastIndex_ {{index "exec method", "regular expression"}} -The `exec` method similarly does not provide a convenient way to start -searching from a given position in the string. But it does provide an -*in*convenient way. +O método `exec` também não possui um modo conveniente de iniciar a busca a partir de uma determinada posição. Mas ele fornece um método não muito prático. {{index ["regular expression", matching], matching, "source property", "lastIndex property"}} -Regular expression objects have properties. One such property is -`source`, which contains the string that expression was created from. -Another property is `lastIndex`, which controls, in some limited -circumstances, where the next match will start. +Expressões regulares possuem propriedades (como `source` que contém a _string_ que originou a expressão). Uma dessas propriedades, `lastIndex`, controla, em algumas circunstâncias, onde a busca começará. {{index [interface, design], "exec method", ["regular expression", global]}} -Those circumstances are that the regular expression must have the -global (`g`) or sticky (`y`) option enabled, and the match must happen -through the `exec` method. Again, a less confusing solution would have -been to just allow an extra argument to be passed to `exec`, but -confusion is an essential feature of JavaScript's regular expression -interface. +Essas circunstâncias são que a expressão regular precisa ter a opção "global" (g) ou sticky (y) habilitada no método `exec`. Novamente, deveria ser da mesma maneira que permitir um argumento extra para o método `exec`, mas coesão não é uma característica que define a sintaxe de expressões regulares em JavaScript. -``` +```js let pattern = /y/g; pattern.lastIndex = 3; let match = pattern.exec("xyzzy"); @@ -912,17 +636,11 @@ console.log(pattern.lastIndex); {{index "side effect", "lastIndex property"}} -If the match was successful, the call to `exec` automatically updates -the `lastIndex` property to point after the match. If no match was -found, `lastIndex` is set back to zero, which is also the value it has -in a newly constructed regular expression object. +Se a correspondência for bem-sucedida, a chamada para `exec` atualiza automaticamente a propriedade `lastIndex` para apontar após a correspondência. Se nenhuma correspondência for encontrada, `lastIndex` é zerado, o que também é o valor que possui um objeto de expressão regular recém-construído. -The difference between the global and the sticky options is that, when -sticky is enabled, the match will succeed only if it starts directly -at `lastIndex`, whereas with global, it will search ahead for a -position where a match can start. +A diferença entre as opções _global_ e _sticky_ é que, quando _sticky_ está habilitado, a correspondência será bem-sucedida apenas se começar diretamente em _lastIndex_, enquanto que com _global_, ela procurará adiante por uma posição onde uma correspondência possa começar. -``` +```js let global = /abc/g; console.log(global.exec("xyz abc")); // → ["abc"] @@ -933,12 +651,9 @@ console.log(sticky.exec("xyz abc")); {{index bug}} -When using a shared regular expression value for multiple `exec` -calls, these automatic updates to the `lastIndex` property can cause -problems. Your regular expression might be accidentally starting at an -index that was left over from a previous call. +Ao usar um valor de expressão regular compartilhado para várias chamadas `exec`, essas atualizações automáticas da propriedade _lastIndex_ podem causar problemas. Sua expressão regular pode estar acidentalmente iniciando no índice que sobrou de uma chamada anterior. -``` +```js let digit = /\d/g; console.log(digit.exec("here it is: 1")); // → ["1"] @@ -948,36 +663,27 @@ console.log(digit.exec("and now: 1")); {{index ["regular expression", global], "match method"}} -Another interesting effect of the global option is that it changes the -way the `match` method on strings works. When called with a global -expression, instead of returning an array similar to that returned by -`exec`, `match` will find _all_ matches of the pattern in the string -and return an array containing the matched strings. +Outro efeito interessante da opção _global_ é que ela muda a maneira como o método de correspondência funciona nas strings. Quando chamado com uma expressão global, em vez de retornar uma _array_ semelhante àquela retornada por `exec`, `match` encontrará todas as correspondências do padrão na _string_ e retornará uma _array_ contendo as strings correspondentes. -``` +```js console.log("Banana".match(/an/g)); // → ["an", "an"] ``` -So be cautious with global regular expressions. The cases where they -are necessary—calls to `replace` and places where you want to -explicitly use `lastIndex`—are typically the only places where you -want to use them. +Então tenha cuidado com expressões regulares globais. Use-as nos casos em que são necessárias, como em `replace` ou em lugares onde você deseja usar explicitamente o _lastIndex_ que normalmente são os únicos lugares que você pode querer utilizá-las. -### Looping over matches +## Loop sobre correspondências {{index "lastIndex property", "exec method", loop}} -A common thing to do is to scan through all occurrences of a pattern -in a string, in a way that gives us access to the match object in the -loop body. We can do this by using `lastIndex` and `exec`. +Um padrão comum é buscar todas as ocorrências de um padrão em uma _string_, com acesso a todos os grupos encontrados e ao índice onde foram encontrados, usando _lastIndex_ e `exec`. -``` +```js let input = "A string with 3 numbers in it... 42 and 88."; let number = /\b\d+\b/g; let match; -while (match = number.exec(input)) { - console.log("Found", match[0], "at", match.index); +while ((match = number.exec(input))) { + console.log("Found", match[0], "at", match.index); } // → Found 3 at 14 // Found 42 at 33 @@ -986,25 +692,17 @@ while (match = number.exec(input)) { {{index "while loop", ["= operator", "as expression"], [binding, "as state"]}} -This makes use of the fact that the value of an ((assignment)) -expression (`=`) is the assigned value. So by using `match = -number.exec(input)` as the condition in the `while` statement, we -perform the match at the start of each iteration, save its result in a -binding, and stop looping when no more matches are found. +Usa-se o fato que o valor de uma expressão de definição (`=`) é o valor assinalado. Então usando-se `match = re.exec(input)` como a condição no bloco `while`, podemos buscar no início de cada iteração. {{id ini}} -## Parsing an INI file + +## Analisando um arquivo .ini {{index comment, "file format", "enemies example", "INI file"}} -To conclude the chapter, we'll look at a problem that calls for -((regular expression))s. Imagine we are writing a program to -automatically collect information about our enemies from the -((Internet)). (We will not actually write that program here, just the -part that reads the ((configuration)) file. Sorry.) The configuration -file looks like this: +Para concluir o capítulo, veremos agora um problema real que exige o uso de expressões regulares. Imagine que estamos escrevendo um programa que coleta informação automaticamente da internet dos nossos inimigos. (Não vamos escrever um programa aqui, apenas a parte que lê o arquivo de configuração, desculpe desapontá-los). Este arquivo tem a seguinte aparência: -```{lang: "text/plain"} +```js searchengine=https://duckduckgo.com/?q=$1 spitefulness=9.7 @@ -1023,36 +721,20 @@ outputdir=/home/marijn/enemies/davaeorn {{index grammar}} -The exact rules for this format (which is a widely used format, -usually called an _INI_ file) are as follows: - -- Blank lines and lines starting with semicolons are ignored. - -- Lines wrapped in `[` and `]` start a new ((section)). - -- Lines containing an alphanumeric identifier followed by an `=` - character add a setting to the current section. +As regras exatas desse formato (que é um formato muito usado, chamado arquivo .ini) são as seguintes: -- Anything else is invalid. +- Linhas em branco e linhas iniciadas com ponto e vírgula são ignoradas; +- Linhas entre colchetes `[]` iniciam uma nova seção; +- Linhas contendo um identificador alfanumérico seguido por um caractere = adicionam uma configuração à seção atual; +- Qualquer outra coisa é inválida. -Our task is to convert a string like this into an object whose -properties hold strings for settings written before the first -section header and subobjects for sections, with those subobjects -holding the section's settings. +Nossa tarefa é converter uma _string_ como essa em um _array_ de objetos, cada uma com um nome e um _array_ de pares nome/valor. Precisaremos de um objeto para cada seção e outro para as configurações de seção. {{index "carriage return", "line break", "newline character"}} -Since the format has to be processed ((line)) by line, splitting up -the file into separate lines is a good start. We saw -the `split` method in [Chapter ?](data#split). -Some operating systems, however, use not just a newline character to -separate lines but a carriage return character followed by a newline -(`"\r\n"`). Given that the `split` method also allows a regular -expression as its argument, we can use a regular expression like -`/\r?\n/` to split in a way that allows both `"\n"` and `"\r\n"` -between lines. - -```{startCode: true} +Já que o formato precisa ser processado linha a linha, dividir em linhas separadas é um bom começo. Nos vimos o método `split` no capítulo 4. Entretanto alguns sistemas operacionais não usam apenas um caractere de nova linha para separar linhas, mas um caractere de retorno seguido por um de nova linha (`_\r\n_`). Desse modo o método `split` ,em uma expressão regular com `/\r?\n/` permite separar os dois modos, com `\n` e `\r\n` entre linhas. + +```js function parseINI(string) { // Start with an object to hold the top-level fields let result = {}; @@ -1075,74 +757,40 @@ name=Vasilis [address] city=Tessaloniki`)); // → {name: "Vasilis", address: {city: "Tessaloniki"}} +} ``` {{index "parseINI function", parsing}} -The code goes over the file's lines and builds up an object. -Properties at the top are stored directly into that object, whereas -properties found in sections are stored in a separate section object. -The `section` binding points at the object for the current section. +O código percorre as linhas do arquivo e constrói um objeto. As propriedades na parte superior são armazenadas diretamente nesse objeto, enquanto as propriedades encontradas nas seções são armazenadas em um objeto de seção separado. A `section` de conexão aponta para o objeto da seção atual. -There are two kinds of significant lines—section headers or property -lines. When a line is a regular property, it is stored in the current -section. When it is a section header, a new section object is created, -and `section` is set to point at it. +Existem dois tipos de linhas significativas - cabeçalhos de seção ou linhas de propriedade. Quando uma linha é uma propriedade regular, ela é armazenada na seção atual. Quando é um cabeçalho de seção, um novo objeto de seção é criado e a `section` é definida para apontar para ele. {{index "caret character", "dollar sign", boundary}} -Note the recurring use of `^` and `$` to make sure the expression -matches the whole line, not just part of it. Leaving these out results -in code that mostly works but behaves strangely for some input, which -can be a difficult bug to track down. +Observe o uso recorrente de `ˆ` e `$` para certificar-se que a expressão busca em toda a linha, não apenas em parte dela. Esquecer isso é um erro comum, que resulta um código que funciona mas retorna resultados estranhos para algumas entradas, o que pode ser um bug difícil de encontrar. {{index "if keyword", assignment, ["= operator", "as expression"]}} -The pattern `if (match = string.match(...))` is similar to the trick -of using an assignment as the condition for `while`. You often aren't -sure that your call to `match` will succeed, so you can access the -resulting object only inside an `if` statement that tests for this. To -not break the pleasant chain of `else if` forms, we assign the result -of the match to a binding and immediately use that assignment as the -test for the `if` statement. +O padrão `if (match = string.match(...))` é parecido com o truque que foi usado como definição do `while` antes. Geralmente não temos certeza se a expressão encontrará algo. Mas você só deseja fazer algo com o resultado se ele não for nulo, então você precisa testar ele antes. Para não quebrar a agradável sequência de `else if` atribuímos o resultado da correspondência a uma conexão e imediatamente usamos essa atribuição como teste para a declaração de `if`. {{index [parentheses, "in regular expressions"]}} -If a line is not a section header or a property, the function checks -whether it is a comment or an empty line using the expression -`/^\s*(;.*)?$/`. Do you see how it works? The part between the -parentheses will match comments, and the `?` makes sure it also -matches lines containing only whitespace. When a line doesn't match -any of the expected forms, the function throws an exception. +Se uma linha não for um cabeçalho de seção ou uma propriedade, a função verifica se é um comentário ou uma linha vazia usando a expressão `/^\s*(;.*)?$/`. Você vê como isso funciona? A parte entre os parênteses corresponderá aos comentários e o "?" se certificará de que também corresponda às linhas que contêm apenas espaços em branco. Quando uma linha não corresponde a nenhuma das form esperadas, a função resulta em uma exceção. -## International characters +## Caracteres internacionais {{index internationalization, Unicode, ["regular expression", internationalization]}} -Because of JavaScript's initial simplistic implementation and the fact -that this simplistic approach was later set in stone as ((standard)) -behavior, JavaScript's regular expressions are rather dumb about -characters that do not appear in the English language. For example, as -far as JavaScript's regular expressions are concerned, a "((word -character))" is only one of the 26 characters in the Latin alphabet -(uppercase or lowercase), decimal digits, and, for some reason, the -underscore character. Things like _é_ or _β_, which most definitely -are word characters, will not match `\w` (and _will_ match uppercase -`\W`, the nonword category). +Devido a uma implementação inicial simplista e o fato que esta abordagem simplista mais tarde foi gravada em pedra como comportamento padrão, expressões regulares do JavaScript são um pouco estúpidas sobre caracteres que não parecem na língua inglesa. Por exemplo, "caracteres palavra", nesse contexto, atualmente significam apenas os 26 caracteres do alfabeto latino. Coisas como `é` ou `β`, que definitivamente são caracteres de palavras, não encontrarão resultados com `\w` (e serão encontradas com o marcador de letras maiúsculas `\W`). {{index [whitespace, matching]}} -By a strange historical accident, `\s` (whitespace) does not have this -problem and matches all characters that the Unicode standard considers -whitespace, including things like the ((nonbreaking space)) and the -((Mongolian vowel separator)). +Devido a um estranho acidente histórico, `\s` (espaço em branco) é diferente, e irá encontrar todos os caracteres que o padrão _Unicode_ considera como espaço em branco, como espaços sem quebra ou o separador de vogais do alfabeto Mongol. -Another problem is that, by default, regular expressions work on code -units, as discussed in [Chapter ?](higher_order#code_units), not -actual characters. This means characters that are composed of two -code units behave strangely. +Outro problema é que, por padrão, as expressões regulares funcionam em unidades de código, conforme discutido no Capítulo 5, e não em caracteres reais. Isso significa que os caracteres compostos por duas unidades de código se comportam de maneira estranha. -``` +```js console.log(/🍎{3}/.test("🍎🍎🍎")); // → false console.log(/<.>/.test("<🌹>")); @@ -1151,24 +799,15 @@ console.log(/<.>/u.test("<🌹>")); // → true ``` -The problem is that the 🍎 in the first line is treated as two code -units, and the `{3}` part is applied only to the second one. -Similarly, the dot matches a single code unit, not the two that make -up the rose ((emoji)). +O problema é que o emoji `🍎` na primeira linha é tratado como duas unidades de código e a `{3}` parte é aplicada apenas à segunda. Da mesma forma, o ponto corresponde a uma única unidade de código, não aos dois que compõem o emoji rosa `🌹`. -You must add a `u` option (for ((Unicode))) to your regular -expression to make it treat such characters properly. The wrong -behavior remains the default, unfortunately, because changing that -might cause problems for existing code that depends on it. +Você deve adicionar uma opção `u` (para o _Unicode_) à sua expressão regular que ele trate esses caracteres adequadamente. O comportamento incorreto permanece como padrão, infelizmente, porque alterá-lo pode causar problemas para o código existente que depende dele. {{index "character category", [Unicode, property]}} -Though this was only just standardized and is, at the time of writing, -not widely supported yet, it is possible to use `\p` in a regular -expression (that must have the Unicode option enabled) to match all -characters to which the Unicode standard assigns a given property. +Embora isso tenha sido apenas padronizado e, no momento da escrita, não seja amplamente suportado ainda, é possível usar `\p` em uma expressão regular (que deve ter a opção _Unicode_ habilitada) para combinar todos os caracteres aos quais o padrão _Unicode_ atribui à determinada propriedade. -```{test: never} +```js console.log(/\p{Script=Greek}/u.test("α")); // → true console.log(/\p{Script=Arabic}/u.test("α")); @@ -1179,225 +818,180 @@ console.log(/\p{Alphabetic}/u.test("!")); // → false ``` -Unicode defines a number of useful properties, though finding the one -that you need may not always be trivial. You can use the -`\p{Property=Value}` notation to match any character that has the -given value for that property. If the property name is left off, as in -`\p{Name}`, the name is assumed to be either a binary property such as -`Alphabetic` or a category such as `Number`. +O _Unicode_ define várias propriedades úteis, embora encontrar aquela que você precisa nem sempre seja relevante. Você pode usar `\p{Property=Value}` para que corresponda a qualquer caractere que tenha o valor fornecido para essa propriedade. Se o nome da propriedade for deixado de fora, como em `\p{Name}`, o nome será considerado uma propriedade binária, como `Alphabetic` ou uma categoria, como `Number`. {{id summary_regexp}} -## Summary +## Sumário -Regular expressions are objects that represent patterns in strings. -They use their own language to express these patterns. +Expressões regulares são objetos que representam padrões em _strings_. Eles usam sua própria sintaxe para expressar esses padrões. {{table {cols: [1, 5]}}} -| `/abc/` | A sequence of characters -| `/[abc]/` | Any character from a set of characters -| `/[^abc]/` | Any character _not_ in a set of characters -| `/[0-9]/` | Any character in a range of characters -| `/x+/` | One or more occurrences of the pattern `x` -| `/x+?/` | One or more occurrences, nongreedy -| `/x*/` | Zero or more occurrences -| `/x?/` | Zero or one occurrence -| `/x{2,4}/` | Two to four occurrences -| `/(abc)/` | A group -| `/a|b|c/` | Any one of several patterns -| `/\d/` | Any digit character -| `/\w/` | An alphanumeric character ("word character") -| `/\s/` | Any whitespace character -| `/./` | Any character except newlines -| `/\b/` | A word boundary -| `/^/` | Start of input -| `/$/` | End of input - -A regular expression has a method `test` to test whether a given -string matches it. It also has a method `exec` that, when a match is -found, returns an array containing all matched groups. Such an array -has an `index` property that indicates where the match started. - -Strings have a `match` method to match them against a regular -expression and a `search` method to search for one, returning only the -starting position of the match. Their `replace` method can replace -matches of a pattern with a replacement string or function. - -Regular expressions can have options, which are written after the -closing slash. The `i` option makes the match case insensitive. The -`g` option makes the expression _global_, which, among other things, -causes the `replace` method to replace all instances instead of just -the first. The `y` option makes it sticky, which means that it will -not search ahead and skip part of the string when looking for a match. -The `u` option turns on Unicode mode, which fixes a number of problems -around the handling of characters that take up two code units. - -Regular expressions are a sharp ((tool)) with an awkward handle. They -simplify some tasks tremendously but can quickly become unmanageable -when applied to complex problems. Part of knowing how to use them is -resisting the urge to try to shoehorn things that they cannot cleanly -express into them. - -## Exercises + /abc/ Sequência de caracteres + /[abc]/ Qualquer caractere do conjunto + /[^abc]/ Qualquer caractere que não seja do conjunto + /[0-9]/ Qualquer caractere no intervalo de caracteres + /x+/ Uma ou mais ocorrências do padrão + /x+?/ Uma ou mais ocorrências do padrão, não obrigatório + /x*/ Zero ou mais ocorrências + /x?/ Zero ou uma ocorrência + /x{2,4}/ Entre duas e quatro ocorrências + /(abc)+/ Agrupamento + /a|b|c/ Padrões alternativos + /\d/ Caracteres dígitos + /\w/ Caracteres alfanuméricos ("caracteres palavra") + /\s/ caracteres espaço em branco + /./ Todos caracteres exceto quebras de linha + /\b/ Limite de palavra + /^/ Início da entrada + /$/ Final da Entrada + +Uma expressão regular possui um método `test` para testar quando um padrão é encontrado em uma _string_, um método `exec` que quando encontra um resultado retorna um _array_ com todos os grupos encontrados e uma propriedade `index` que indica onde o resultado inicia. + +_Strings_ possuem um método `match` para testá-las contra uma expressão regular e um método `search` para buscar por um resultado. O método `replace` pode substituir as correspondências de um padrão por uma string ou função de substituição. + +Expressões regulares podem ter opções configuradas (_flags_), que são escritas após o fechamento da barra. A opção `i` faz a busca sem se importar se é maiúscula ou minúscula, a opção `g` faz a busca global, que, entre outras coisas, faz o método `replace` substituir todas as ocorrências, em vez de só a primeira. A opção `y` o torna aderente, o que significa que ele não pesquisará à frente e ignorará parte da _string_ ao procurar por uma correspondência. A opção `u` ativa o modo _Unicode_, que corrige uma série de problemas em torno do tratamento de caracteres que ocupam duas unidades de código. + +Expressões regulares são uma ferramenta precisa que possui um manuseio estranho. Elas simplificarão muito algumas tarefas simples, mas rapidamente se tornarão inviáveis quando aplicadas a tarefas mais complexas. Saber quando usá-las é útil. Parte do conhecimento de saber **quando** usá-las é o conhecimento de saber **como** usá-las e quando desistir do seu uso e procurar uma abordagem mais simples. + +## Exercícios {{index debugging, bug}} -It is almost unavoidable that, in the course of working on these -exercises, you will get confused and frustrated by some regular -expression's inexplicable ((behavior)). Sometimes it helps to enter -your expression into an online tool like -[_https://debuggex.com_](https://www.debuggex.com/) to see whether its -visualization corresponds to what you intended and to ((experiment)) -with the way it responds to various input strings. +É quase inevitável que, no decorrer do trabalho, você irá ficar confuso e frustado por algum comportamento estranho de uma expressão regular. O que ajuda às vezes é colocar a sua expressão em uma ferramenta online como [debuggex.com](debuggex.com), para ver se a visualização corresponde à sua intenção inicial, e rapidamente ver como ela responde à várias _strings_ diferentes. -### Regexp golf +## Regexp golf {{index "program size", "code golf", "regexp golf (exercise)"}} -_Code golf_ is a term used for the game of trying to express a -particular program in as few characters as possible. Similarly, -_regexp golf_ is the practice of writing as tiny a regular expression -as possible to match a given pattern, and _only_ that pattern. +"_Code Golf_" é um termo usado para o jogo de tentar escrever um programa com o menor número de caracteres possível. Parecido, o `regexp golf` é a prática de escrever pequenas expressões regulares para achar um determinado padrão, e apenas esse padrão. {{index boundary, matching}} -For each of the following items, write a ((regular expression)) to -test whether any of the given substrings occur in a string. The -regular expression should match only strings containing one of the -substrings described. Do not worry about word boundaries unless -explicitly mentioned. When your expression works, see whether you can -make it any smaller. +Para cada um dos seguintes itens, escreva uma expressão regular que testa quando qualquer das _sub-strings_ dadas que ocorrem em um _string_. A expressão regular deverá achar apenas _strings_ contendo uma das _sub-strings_ dadas. Não se preocupe com limites de palavras a não ser que seja explicitamente pedido. Quando a sua expressão funcionar, veja se consegue fazê-la ficar menor. - 1. _car_ and _cat_ - 2. _pop_ and _prop_ - 3. _ferret_, _ferry_, and _ferrari_ - 4. Any word ending in _ious_ - 5. A whitespace character followed by a period, comma, colon, or semicolon - 6. A word longer than six letters - 7. A word without the letter _e_ (or _E_) + 1. "car" e "cat" + 2."pop" e "prop" + 3."ferret", "ferry", e "ferrari" + 4.Qualquer palavra terminando em "ious" + 5.Um espaço em branco seguido por um ponto, vírgula, 6.dois-pontos, ou ponto-e-vírgula + 7.Uma palavra com mais de seis letras + 8.Uma palavra sem a letra "e" (ou E) -Refer to the table in the [chapter summary](regexp#summary_regexp) for -help. Test each solution with a few test strings. +Consulte a tabela no capítulo _Sumário_ para ajuda. +Teste cada solução encontrada com alguns testes com _strings_. {{if interactive -``` -// Fill in the regular expressions -verify(/.../, - ["my car", "bad cats"], - ["camper", "high art"]); +```js +// Fill in the regular expressions -verify(/.../, - ["pop culture", "mad props"], - ["plop", "prrrop"]); +verify(/.../, ["my car", "bad cats"], ["camper", "high art"]); -verify(/.../, - ["ferret", "ferry", "ferrari"], - ["ferrum", "transfer A"]); +verify(/.../, ["pop culture", "mad props"], ["plop", "prrrop"]); -verify(/.../, - ["how delicious", "spacious room"], - ["ruinous", "consciousness"]); +verify(/.../, ["ferret", "ferry", "ferrari"], ["ferrum", "transfer A"]); -verify(/.../, - ["bad punctuation ."], - ["escape the period"]); +verify(/.../, ["how delicious", "spacious room"], ["ruinous", "consciousness"]); -verify(/.../, - ["hottentottententen"], - ["no", "hotten totten tenten"]); +verify(/.../, ["bad punctuation ."], ["escape the period"]); -verify(/.../, - ["red platypus", "wobbling nest"], - ["earth bed", "learning ape", "BEET"]); +verify( + /.../, + ["Siebentausenddreihundertzweiundzwanzig"], + ["no", "three small words"] +); +verify( + /.../, + ["red platypus", "wobbling nest"], + ["earth bed", "learning ape", "BEET"] +); function verify(regexp, yes, no) { - // Ignore unfinished exercises - if (regexp.source == "...") return; - for (let str of yes) if (!regexp.test(str)) { - console.log(`Failure to match '${str}'`); - } - for (let str of no) if (regexp.test(str)) { - console.log(`Unexpected match for '${str}'`); - } + // Ignore unfinished exercises + if (regexp.source == "...") return; + for (let str of yes) + if (!regexp.test(str)) { + console.log(`Failure to match '${str}'`); + } + for (let str of no) + if (regexp.test(str)) { + console.log(`Unexpected match for '${str}'`); + } } ``` if}} -### Quoting style +## Estilo de aspas {{index "quoting style (exercise)", "single-quote character", "double-quote character"}} -Imagine you have written a story and used single ((quotation mark))s -throughout to mark pieces of dialogue. Now you want to replace all the -dialogue quotes with double quotes, while keeping the single quotes -used in contractions like _aren't_. +Imagine que você escreveu um texto e usou aspas simples por toda parte. Agora você deseja substituir todas que realmente possuem algum texto com aspas duplas, mas não as usadas em contrações de texto com _aren't_. {{index "replace method"}} -Think of a pattern that distinguishes these two -kinds of quote usage and craft a call to the `replace` method that -does the proper replacement. +Pense em um padrão que faça distinção entre esses dois usos de aspas e faça uma chamada que substitua apenas nos lugares apropriados. {{if interactive -```{test: no} + +```js let text = "'I'm the cook,' he said, 'it's my job.'"; // Change this call. console.log(text.replace(/A/g, "B")); // → "I'm the cook," he said, "it's my job." ``` + if}} {{hint {{index "quoting style (exercise)", boundary}} -The most obvious solution is to replace only quotes with a nonword -character on at least one side—something like `/\W'|'\W/`. But you -also have to take the start and end of the line into account. +**Dicas** + +A solução mais óbvia é substituir apenas as aspas que não estão cercadas de caracteres de palavra. A primeira expressão vem à mente é `/\W'\W/`, Mas você também deve levar em consideração o início e o fim da linha. {{index grouping, "replace method", [parentheses, "in regular expressions"]}} -In addition, you must ensure that the replacement also includes the -characters that were matched by the `\W` pattern so that those are not -dropped. This can be done by wrapping them in parentheses and -including their groups in the replacement string (`$1`, `$2`). Groups -that are not matched will be replaced by nothing. +Além disso, você deve garantir que a substituição também inclua os caracteres que foram correspondidos pelo padrão `\W` para que eles não sejam eliminados. Isso pode ser feito envolvendo-os entre parênteses e incluindo seus grupos substituindo pela _string_ ( `$1`, `$2`). Os grupos que não tiverem correspondência serão substituídos por nada. hint}} -### Numbers again +### Novamente números {{index sign, "fractional number", [syntax, number], minus, "plus character", exponent, "scientific notation", "period character"}} -Write an expression that matches only JavaScript-style ((number))s. It -must support an optional minus _or_ plus sign in front of the number, -the decimal dot, and exponent notation—`5e-3` or `1E10`—again with an -optional sign in front of the exponent. Also note that it is not -necessary for there to be digits in front of or after the dot, but the -number cannot be a dot alone. That is, `.5` and `5.` are valid -JavaScript numbers, but a lone dot _isn't_. +Escreva uma expressão que encontre (apenas) números no estilo JavaScript. Isso significa que precisa suportar um sinal de menor ou maior, opcional, na frente do número, um ponto decimal e a notação exponencial `—5e-3` ou `1E10—`, novamente com o sinal opcional na frente dele. . Observe também que não é necessário que haja dígitos antes ou depois do ponto, mas o número não pode ser apenas um ponto. Assim, `.5` e `5.` são números JavaScript válidos, mas apenas o ponto não é. {{if interactive -```{test: no} -// Fill in this regular expression. + +```js +// Preencha esta expressão regular let number = /^...$/; // Tests: -for (let str of ["1", "-1", "+15", "1.55", ".5", "5.", - "1.3e2", "1E-4", "1e+12"]) { - if (!number.test(str)) { - console.log(`Failed to match '${str}'`); - } +for (let str of [ + "1", + "-1", + "+15", + "1.55", + ".5", + "5.", + "1.3e2", + "1E-4", + "1e+12", +]) { + if (!number.test(str)) { + console.log(`Failed to match '${str}'`); + } } -for (let str of ["1a", "+-1", "1.2.3", "1+1", "1e4.5", - ".5.", "1f5", "."]) { - if (number.test(str)) { - console.log(`Incorrectly accepted '${str}'`); - } +for (let str of ["1a", "+-1", "1.2.3", "1+1", "1e4.5", ".5.", "1f5", "."]) { + if (number.test(str)) { + console.log(`Incorrectly accepted '${str}'`); + } } ``` @@ -1407,23 +1001,16 @@ if}} {{index ["regular expression", escaping], ["backslash character", "in regular expressions"]}} -First, do not forget the backslash in front of the period. +Primeiro, não esqueça da barra invertida em frente ao ponto. -Matching the optional ((sign)) in front of the ((number)), as well as -in front of the ((exponent)), can be done with `[+\-]?` or `(\+|-|)` -(plus, minus, or nothing). +Achar o sinal opcional na frente do número, como na frente do exponencial, pode ser feito com `[+\-]?` ou `(+|-|)` (mais, menos ou nada). {{index "pipe character"}} -The more complicated part of the exercise is the problem of matching -both `"5."` and `".5"` without also matching `"."`. For this, a good -solution is to use the `|` operator to separate the two cases—either -one or more digits optionally followed by a dot and zero or more -digits _or_ a dot followed by one or more digits. +A parte mais complicada deste exercício provavelmente é a dificuldade de achar `5.` e `.5` sem achar também o `.`. Para isso, achamos que a melhor solução é usar o operador `|` para separar os dois casos, um ou mais dígitos opcionalmente seguidos por um ponto e zero ou mais dígitos, ou um ponto seguido por um ou mais dígitos. {{index exponent, "case sensitivity", ["regular expression", flags]}} -Finally, to make the _e_ case insensitive, either add an `i` option to -the regular expression or use `[eE]`. +Finalmente, fazer o "e" _case-insensitive_, ou adicional a opção `i` à expressão regular ou usar `[eE]`. hint}}