Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quantifiers +, *, ? and {n} #429

Merged
merged 3 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

Solution:
Solução:

```js run
let regexp = /\.{3,}/g;
alert( "Hello!... How goes?.....".match(regexp) ); // ..., .....
alert( "Olá!... Como está?.....".match(regexp) ); // ..., .....
```

Please note that the dot is a special character, so we have to escape it and insert as `\.`.
Note que o ponto é um caractere especial (também conhecido como metacaractere), então devemos escapá-lo usando uma contrabarra: `\.`.
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ importance: 5

---

# How to find an ellipsis "..." ?
# Como encontrar reticências "..." ?

Create a regexp to find ellipsis: 3 (or more?) dots in a row.
Crie uma expressão regular que reconhece reticências: 3 (ou mais?) pontos consecutivos.

Check it:
Seu teste:

```js
let regexp = /your regexp/g;
alert( "Hello!... How goes?.....".match(regexp) ); // ..., .....
let regexp = /sua expressão/g;
alert( "Olá!... Como está?.....".match(regexp) ); // ..., .....
```
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
We need to look for `#` followed by 6 hexadecimal characters.
Precisamos buscar pela cerquilha `#` seguida por 6 caracteres hexadecimais.

A hexadecimal character can be described as `pattern:[0-9a-fA-F]`. Or if we use the `pattern:i` flag, then just `pattern:[0-9a-f]`.
Um caractere hexadecimal pode ser descrito como `pattern:[0-9a-fA-F]`, ou usando a opção `pattern:i`, apenas `pattern:[0-9a-f]`.

Then we can look for 6 of them using the quantifier `pattern:{6}`.
Podemos então buscar por 6 deles usando o quantificador `pattern:{6}`.

As a result, we have the regexp: `pattern:/#[a-f0-9]{6}/gi`.
Nosso resultado final é a expressão: `pattern:/#[a-f0-9]{6}/gi`.

```js run
let regexp = /#[a-f0-9]{6}/gi;
Expand All @@ -14,18 +14,18 @@ let str = "color:#121212; background-color:#AA00ef bad-colors:f#fddee #fd2"
alert( str.match(regexp) ); // #121212,#AA00ef
```

The problem is that it finds the color in longer sequences:
Mas temos um problema, essa expressão captura cores em sequências maiores:

```js run
alert( "#12345678".match( /#[a-f0-9]{6}/gi ) ) // #123456
```

To fix that, we can add `pattern:\b` to the end:
Para consertar isso, adicionamos o `pattern:\b` ao final:

```js run
// color
// cor válida
alert( "#123456".match( /#[a-f0-9]{6}\b/gi ) ); // #123456

// not a color
// cor inválida
alert( "#12345678".match( /#[a-f0-9]{6}\b/gi ) ); // null
```
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# Regexp for HTML colors
# Regex para cores hexadecimais
Peruibeloko marked this conversation as resolved.
Show resolved Hide resolved

Create a regexp to search HTML-colors written as `#ABCDEF`: first `#` and then 6 hexadecimal characters.
Crie uma expressão regular que reconhece cores escritas no formato `#ABCDEF`: Primeiro um `#`, seguido de 6 caracteres hexadecimais

An example of use:
Um caso de uso para a expressão:

```js
let regexp = /...your regexp.../
let regexp = /...sua expressão.../

let str = "color:#121212; background-color:#AA00ef bad-colors:f#fddee #fd2 #12345678";

alert( str.match(regexp) ) // #121212,#AA00ef
```

P.S. In this task we do not need other color formats like `#123` or `rgb(1,2,3)` etc.
P.S. Nesse exercício nós não precisamos de outros formatos de cor, como o `#123` ou `rgb(1,2,3)`, etc.
99 changes: 50 additions & 49 deletions 9-regular-expressions/09-regexp-quantifiers/article.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,46 @@
# Quantifiers +, *, ? and {n}
# Quantificadores +, *, ? e {n}

Let's say we have a string like `+7(903)-123-45-67` and want to find all numbers in it. But unlike before, we are interested not in single digits, but full numbers: `7, 903, 123, 45, 67`.
Digamos que temos a string `+7(903)-123-45-67` em mãos e gostaríamos de encontrar todos os números dela. Entretanto, diferente de casos anteriores, não estamos interessados em dígitos soltos, mas sim nos números inteiros: `7, 903, 123, 45, 67`.

A number is a sequence of 1 or more digits `pattern:\d`. To mark how many we need, we can append a *quantifier*.
Um número é uma sequência de 1 ou mais dígitos `pattern:\d`. Para determinar quantos desses precisamos, usamos um *quantificador*.

## Quantity {n}
## Quantidade {n}

The simplest quantifier is a number in curly braces: `pattern:{n}`.
O quantificador mais simples é um número entre chaves: `pattern:{n}`.

A quantifier is appended to a character (or a character class, or a `[...]` set etc) and specifies how many we need.
Quantificadores são colocados após um caractere (ou uma classe de caracteres, ou um conjunto `[...]`, etc.) e especifica quantos do elemento anterior nós precisamos.

It has a few advanced forms, let's see examples:
Ele possui algumas formas avançadas, vejamos alguns exemplos:

The exact count: `pattern:{5}`
: `pattern:\d{5}` denotes exactly 5 digits, the same as `pattern:\d\d\d\d\d`.
Quantidade exata: `pattern:{5}`
: `pattern:\d{5}` representa exatamente 5 dígitos, idêntico a `pattern:\d\d\d\d\d`.

The example below looks for a 5-digit number:
O exemplo abaixo procura por um número de 5 dígitos:

```js run
alert( "I'm 12345 years old".match(/\d{5}/) ); // "12345"
alert( "Eu tenho 12345 anos de idade".match(/\d{5}/) ); // "12345"
```

We can add `\b` to exclude longer numbers: `pattern:\b\d{5}\b`.
Podemos usar o `\b` para não reconhecer números maiores: `pattern:\b\d{5}\b`.

The range: `pattern:{3,5}`, match 3-5 times
: To find numbers from 3 to 5 digits we can put the limits into curly braces: `pattern:\d{3,5}`
Um alcance: `pattern:{3,5}`, repetição de 3 a 5 vezes
: Para encontrar números de 3 a 5 dígitos, podemos usar os limites entre chaves e separados por uma vírgula: `pattern:\d{3,5}`

```js run
alert( "I'm not 12, but 1234 years old".match(/\d{3,5}/) ); // "1234"
alert( "Não tenho 12, mas sim 1234 anos de idade".match(/\d{3,5}/) ); // "1234"
```

We can omit the upper limit.
Também podemos omitir o limite máximo.

Then a regexp `pattern:\d{3,}` looks for sequences of digits of length `3` or more:
Dessa forma, a expressão `pattern:\d{3,}` reconhece qualquer número com no mínimo 3 dígitos:

```js run
alert( "I'm not 12, but 345678 years old".match(/\d{3,}/) ); // "345678"
alert( "Não tenho 12, mas sim 345678 anos de idade".match(/\d{3,}/) ); // "345678"
```

Let's return to the string `+7(903)-123-45-67`.
Voltaremos à string `+7(903)-123-45-67`.

A number is a sequence of one or more digits in a row. So the regexp is `pattern:\d{1,}`:
Um número é uma sequência contínua de um ou mais dígitos. Com base nisso, a expressão regular equivalente é `pattern:\d{1,}`:

```js run
let str = "+7(903)-123-45-67";
Expand All @@ -50,14 +50,14 @@ let numbers = str.match(/\d{1,}/g);
alert(numbers); // 7,903,123,45,67
```

## Shorthands
## Atalhos

There are shorthands for most used quantifiers:
Existem atalhos para os quantificadores mais usados:

`pattern:+`
: Means "one or more", the same as `pattern:{1,}`.
: Representa "um ou mais da captura anterior", equivalente ao `pattern:{1,}`.

For instance, `pattern:\d+` looks for numbers:
O padrão `pattern:\d+`, por exemplo, encontra números:

```js run
let str = "+7(903)-123-45-67";
Expand All @@ -66,77 +66,78 @@ There are shorthands for most used quantifiers:
```

`pattern:?`
: Means "zero or one", the same as `pattern:{0,1}`. In other words, it makes the symbol optional.
: Representa "zero ou um da captura anterior", equivalente ao `pattern:{0,1}`; marca partes da expressão como opcionais.

For instance, the pattern `pattern:ou?r` looks for `match:o` followed by zero or one `match:u`, and then `match:r`.
O padrão `pattern:ou?r`, por exemplo, busca por `match:o` seguido de zero ou um `match:u`, seguido de um `match:r`.

So, `pattern:colou?r` finds both `match:color` and `match:colour`:
Dessa forma, `pattern:colou?r` reconhece ambos `match:color` e `match:colour`:

```js run
// Tradução: Devo escrever cor (em inglês americano) ou cor (em inglês britânico)?
let str = "Should I write color or colour?";

alert( str.match(/colou?r/g) ); // color, colour
```

`pattern:*`
: Means "zero or more", the same as `pattern:{0,}`. That is, the character may repeat any times or be absent.
: Representa "zero ou mais da captura anterior", equivalente ao `pattern:{0,}`; partes da expressão afetadas por esse quantificador podem se repetir indefinidamente ou não estarem presentes

For example, `pattern:\d0*` looks for a digit followed by any number of zeroes (may be many or none):
Por exemplo: O padrão `pattern:\d0*` procura por um dígito seguido de qualquer quantidade de zeros (nenhum ou quantos tiverem):

```js run
alert( "100 10 1".match(/\d0*/g) ); // 100, 10, 1
```

Compare it with `pattern:+` (one or more):
Comparando com o `pattern:+` (um ou mais):

```js run
alert( "100 10 1".match(/\d0+/g) ); // 100, 10
// 1 not matched, as 0+ requires at least one zero
// 1 não é reconhecido, já que 0+ requer ao menos uma ocorrência do 0
```

## More examples
## Outros exemplos

Quantifiers are used very often. They serve as the main "building block" of complex regular expressions, so let's see more examples.
Quantificadores são usados muito frequentemente. Eles servem como um dos principais componentes de expressões regulares complexas; vejamos mais alguns exemplos.

**Regexp for decimal fractions (a number with a floating point): `pattern:\d+\.\d+`**
**Regex para números com casas decimais: `pattern:\d+\.\d+`**

In action:
Em ação:
```js run
alert( "0 1 12.345 7890".match(/\d+\.\d+/g) ); // 12.345
```

**Regexp for an "opening HTML-tag without attributes", such as `<span>` or `<p>`.**
**Regex de uma abertura de elemento HTML sem atributos, como um `<span>` ou um `<p>`.**

1. The simplest one: `pattern:/<[a-z]+>/i`
1. O mais simples: `pattern:/<[a-z]+>/i`

```js run
alert( "<body> ... </body>".match(/<[a-z]+>/gi) ); // <body>
```

The regexp looks for character `pattern:'<'` followed by one or more Latin letters, and then `pattern:'>'`.
A expressão busca pelo caractere `pattern:'<'` seguido de uma ou mais letras do alfabeto latino, seguido de um caractere `pattern:'>'`.

2. Improved: `pattern:/<[a-z][a-z0-9]*>/i`
2. Melhorado: `pattern:/<[a-z][a-z0-9]*>/i`

According to the standard, HTML tag name may have a digit at any position except the first one, like `<h1>`.
De acordo com a norma, um elemento HTML pode ter um dígito em qualquer posição exceto a primeira, como no `<h1>`.

```js run
alert( "<h1>Hi!</h1>".match(/<[a-z][a-z0-9]*>/gi) ); // <h1>
alert( "<h1>Oi!</h1>".match(/<[a-z][a-z0-9]*>/gi) ); // <h1>
```

**Regexp "opening or closing HTML-tag without attributes": `pattern:/<\/?[a-z][a-z0-9]*>/i`**
**Regex de uma abertura ou fechamento de um elemento HTML sem atributos: `pattern:/<\/?[a-z][a-z0-9]*>/i`**

We added an optional slash `pattern:/?` near the beginning of the pattern. Had to escape it with a backslash, otherwise JavaScript would think it is the pattern end.
Adicionamos uma barra opcional `pattern:/?` próxima ao começo do padrão. Ela deve ser escapada com uma contrabarra, caso contrário, o JavaScript pode interpretá-lo como o fim da expressão.

```js run
alert( "<h1>Hi!</h1>".match(/<\/?[a-z][a-z0-9]*>/gi) ); // <h1>, </h1>
alert( "<h1>Oi!</h1>".match(/<\/?[a-z][a-z0-9]*>/gi) ); // <h1>, </h1>
```

```smart header="To make a regexp more precise, we often need make it more complex"
We can see one common rule in these examples: the more precise is the regular expression -- the longer and more complex it is.
```smart header="Para tornar uma expressão regular mais precisa, muitas vezes precisamos torná-la mais complexa"
Podemos ver uma característica em comum entre esses exemplos: Quanto mais precisa é a expressão regular, mais comprida e complexa ela se torna.

For instance, for HTML tags we could use a simpler regexp: `pattern:<\w+>`. But as HTML has stricter restrictions for a tag name, `pattern:<[a-z][a-z0-9]*>` is more reliable.
Para elementos HTML, por exemplo, podemos usar uma expressão mais simples: `pattern:<\w+>`. Mas por conta das restrições de possíveis nomes para um elemento HTML, o padrão `pattern:<[a-z][a-z0-9]*>` é mais confiável.

Can we use `pattern:<\w+>` or we need `pattern:<[a-z][a-z0-9]*>`?
Qual devemos usar então, o `pattern:<\w+>` ou o `pattern:<[a-z][a-z0-9]*>`?

In real life both variants are acceptable. Depends on how tolerant we can be to "extra" matches and whether it's difficult or not to remove them from the result by other means.
Na prática, ambas as variações são aceitáveis. Tudo depende de quantas correspondências "extras" podemos aceitar, e qual a dificuldade de removê-las do nosso resultado depois da captura usando outros meios.
```