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

Tradução: factors.qmd #67

Merged
merged 8 commits into from
Mar 31, 2024
Merged
Changes from 1 commit
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
Next Next commit
Tradução: regexps.qmd
scopinho committed Dec 5, 2023

Verified

This commit was signed with the committer’s verified signature.
scala-steward Scala Steward
commit 1456c6905824ee776bb6f774e20c76ff18580251
734 changes: 367 additions & 367 deletions regexps.qmd
Original file line number Diff line number Diff line change
@@ -1,329 +1,329 @@
# Regular expressions {#sec-regular-expressions}
# Expressões regulares {#sec-regular-expressions}

```{r}
#| echo: false
#| results: asis
source("_common.R")
mensagem_capitulo_sem_traducao()
```

## Introduction
## Introdução

In @sec-strings, you learned a whole bunch of useful functions for working with strings.
This chapter will focus on functions that use **regular expressions**, a concise and powerful language for describing patterns within strings.
The term "regular expression" is a bit of a mouthful, so most people abbreviate it to "regex"[^regexps-1] or "regexp".
No @sec-strings, você aprendeu diversas funções úteis para trabalhar com *strings*.
Este capítulo se concentrará em funções que usam **expressões regulares**, uma linguagem concisa e poderosa para descrever padrões dentro de *strings*.
O termo "expressão regular" é um pouco longo, então a maioria das pessoas o abrevia para "regex"[^regexps-1] ou "regexp".

[^regexps-1]: You can pronounce it with either a hard-g (reg-x) or a soft-g (rej-x).
[^regexps-1]: Você pode pronunciá-lo com um g-seco (reg-x) ou um g-suave (rej-x).

The chapter starts with the basics of regular expressions and the most useful stringr functions for data analysis.
We'll then expand your knowledge of patterns and cover seven important new topics (escaping, anchoring, character classes, shorthand classes, quantifiers, precedence, and grouping).
Next, we'll talk about some of the other types of patterns that stringr functions can work with and the various "flags" that allow you to tweak the operation of regular expressions.
We'll finish with a survey of other places in the tidyverse and base R where you might use regexes.
O capítulo começa com os conceitos básicos de expressões regulares e as funções do pacote stringr mais úteis para análise de dados.
Em seguida, expandiremos seu conhecimento sobre padrões (*patterns*) e cobriremos sete novos tópicos importantes (escape, ancoragem, classes de caracteres, classes de abreviações, quantificadores, precedência de agrupamento).
A seguir, falaremos sobre alguns dos outros tipos de padrões com os quais as funções stringr podem trabalhar e os vários "sinalizadores" que permitem ajustar a operação de expressões regulares.
Terminaremos com uma pesquisa de outros lugares do tidyverse e no R base onde você pode usar expressões regulares.

### Prerequisites
### Pré-requisitos

In this chapter, we'll use regular expression functions from stringr and tidyr, both core members of the tidyverse, as well as data from the babynames package.
Neste capítulo, usaremos funções de expressão regular dos pacotes stringr e tidyr, ambos membros principais do tidyverse, bem como dados bebes do pacote dados.

```{r}
#| label: setup
#| message: false
library(tidyverse)
library(babynames)
library(dados)
```

Through this chapter, we'll use a mix of very simple inline examples so you can get the basic idea, the baby names data, and three character vectors from stringr:
Ao longo deste capítulo, usaremos uma combinação de exemplos muito simples em linha (*inline*) para você entender a ideia geral, o conjunto de dados bebes e três vetores de caracteres do pacote stringr que estão em inglês:

- `fruit` contains the names of 80 fruits.
- `words` contains 980 common English words.
- `sentences` contains 720 short sentences.
- `fruit` contém nomes de 80 frutas.
- `words` contém 980 palavras comuns da lingua inglesa.
- `sentences` contém 720 pequenas sentenças.

## Pattern basics {#sec-reg-basics}
## Padrões básicos {#sec-reg-basics}

We'll use `str_view()` to learn how regex patterns work.
We used `str_view()` in the last chapter to better understand a string vs. its printed representation, and now we'll use it with its second argument, a regular expression.
When this is supplied, `str_view()` will show only the elements of the string vector that match, surrounding each match with `<>`, and, where possible, highlighting the match in blue.
Usaremos a função `str_view()` para aprender como os padrões (*patterns*) regex funcionam.
Usamos `str_view()` no capítulo anterior para entender melhor uma *string* vs. sua representação impressa, e agora, a usaremos com seu segundo argumento, uma expressão regular.
Quando este argumento é fornecido, a `str_view()` irá mostrar apenas os elementos correspondentes (*match*) do vetor de *string* , colocando `<>` ao redor de cada correspondência, e, quando possível, enfatizando a correpondência na cor azul.

The simplest patterns consist of letters and numbers which match those characters exactly:
Os padrões mais simples consistem em letras e números que correspondem exatamente a esses caracteres:

```{r}
str_view(fruit, "berry")
```

Letters and numbers match exactly and are called **literal characters**.
Most punctuation characters, like `.`, `+`, `*`, `[`, `]`, and `?`, have special meanings[^regexps-2] and are called **metacharacters**. For example, `.`
will match any character[^regexps-3], so `"a."` will match any string that contains an "a" followed by another character
Letras e números correspondem exatamente à seus respectivos caracteres e são chamados **caracteres literais**.
A maioria dos caracteres de pontuação, como `.`, `+`, `*`, `[`, `]` e `?`, tem significados especiais[^regexps-2] e são chamado de **metacaracteres**. Por exemplo, `.`
corresponde a qualquer caractere[^regexps-3], portanto `"a."` irá corresponder a qualquer *string* que contenha a letra "a" seguida por qualquer outro caractere
:

[^regexps-2]: You'll learn how to escape these special meanings in @sec-regexp-escaping.
[^regexps-2]: Você aprenderá como escapar destes significados especiais na @sec-regexp-escaping.

[^regexps-3]: Well, any character apart from `\n`.
[^regexps-3]: Bem, qualquer caractere exceto `\n`.

```{r}
str_view(c("a", "ab", "ae", "bd", "ea", "eab"), "a.")
```

Or we could find all the fruits that contain an "a", followed by three letters, followed by an "e":
Ou, podemos encontrar todas as frutas que contèm um "a", seguido por três letras, seguidas por um "e":

```{r}
str_view(fruit, "a...e")
```

**Quantifiers** control how many times a pattern can match:
**Quantificadores** controlam quantas vezes um padrão pode ser encontrado:

- `?` makes a pattern optional (i.e. it matches 0 or 1 times)
- `+` lets a pattern repeat (i.e. it matches at least once)
- `*` lets a pattern be optional or repeat (i.e. it matches any number of times, including 0).
- `?` torna um padrão opcional (e.x. corresponde a 0 ou 1 vezes)
- `+` permite que o padrão se repita (e.x. corresponde ao menos uma vez)
- `*` permite que o padrão seja opcional ou se repita (e.x. corresponde a qualquer número de vezes, incluindo 0).

```{r}
# ab? matches an "a", optionally followed by a "b".
# ab? corresponde a "a", opcionalmente seguida por um "b".
str_view(c("a", "ab", "abb"), "ab?")
# ab+ matches an "a", followed by at least one "b".
# ab+ corresponde a um "a", seguido por ao menos um "b".
str_view(c("a", "ab", "abb"), "ab+")
# ab* matches an "a", followed by any number of "b"s.
# ab* corresponde um "a", seguido por qualquer número de "b"s.
str_view(c("a", "ab", "abb"), "ab*")
```

**Character classes** are defined by `[]` and let you match a set of characters, e.g., `[abcd]` matches "a", "b", "c", or "d".
You can also invert the match by starting with `^`: `[^abcd]` matches anything **except** "a", "b", "c", or "d".
We can use this idea to find the words containing an "x" surrounded by vowels, or a "y" surrounded by consonants:
**Classes de caracteres** são definidas por `[]` e permitem que você defina um conjunto de caracteres, e.x., `[abcd]` corresponde a "a", "b", "c" ou "d".
Você também pode inverter a correspondência com um `^`: `[^abcd]` corresponde a qualquer coisa, **exceto** "a", "b", "c" ou "d".
Podemos usar esta ideia para encontrar palavras que contenham um "x" cercado por vogais, ou um "y" cercado por consoantes:

```{r}
str_view(words, "[aeiou]x[aeiou]")
str_view(words, "[^aeiou]y[^aeiou]")
```

You can use **alternation**, `|`, to pick between one or more alternative patterns.
For example, the following patterns look for fruits containing "apple", "melon", or "nut", or a repeated vowel.
Você pode usar a **alternância**, `|`, para selecionar entre um ou mais padrões alternativos.
Por exemplo, os padrões a seguir procuram por frutas contendo "apple", "melon", ou "nut", ou uma vogal repetida.

```{r}
str_view(fruit, "apple|melon|nut")
str_view(fruit, "aa|ee|ii|oo|uu")
```

Regular expressions are very compact and use a lot of punctuation characters, so they can seem overwhelming and hard to read at first.
Don't worry; you'll get better with practice, and simple patterns will soon become second nature.
Let's kick off that process by practicing with some useful stringr functions.
Expressões regulares são bastante compactas e usam diversos caracteres de pontuação, portanto elas podem parecer difíceis de ler e entender no início.
Não se preocupe; você as entenderá melhor com a prática, e padrões simples se tornarão naturais.
Vamos iniciar este processo praticando com algumas funções úteis do stringr.

## Key functions {#sec-stringr-regex-funs}
## Funções chaves {#sec-stringr-regex-funs}

Now that you've got the basics of regular expressions under your belt, let's use them with some stringr and tidyr functions.
In the following section, you'll learn how to detect the presence or absence of a match, how to count the number of matches, how to replace a match with fixed text, and how to extract text using a pattern.
Agora que você tem o básico das expressões regulares em seu cinto de utilidades, vamos usá-las em algumas funções dos pacotes stringr e tidyr.
Na seção a seguir, você aprenderá como detectar a presença ou ausência de correspondências (*matches*), como contar o número de correspondências, como trocar uma correspondência por um texto fixo e como extrair textos usando um padrão (*pattern*).

### Detect matches
### Detectando correspondência

`str_detect()` returns a logical vector that is `TRUE` if the pattern matches an element of the character vector and `FALSE` otherwise:
`str_detect()` retorna uma vetor lógico que ém `TRUE` se o padrão corresponde a um elemento do vetor de caracteres e `FALSE` se não corresponde:

```{r}
str_detect(c("a", "b", "c"), "[aeiou]")
```

Since `str_detect()` returns a logical vector of the same length as the initial vector, it pairs well with `filter()`.
For example, this code finds all the most popular names containing a lower-case "x":
Uma vez que `str_detect()` retorna um vetor lógico de mesmo tamanho que o vetor inicial, ele vai muito bem com a função `filter()`.
Por exemplo, este código encontra todos os nomes mais populares contendo um "x" minúsculo:

```{r}
babynames |>
filter(str_detect(name, "x")) |>
count(name, wt = n, sort = TRUE)
bebes |>
filter(str_detect(nome, "x")) |>
count(nome, wt = n, sort = TRUE)
```

We can also use `str_detect()` with `summarize()` by pairing it with `sum()` or `mean()`: `sum(str_detect(x, pattern))` tells you the number of observations that match and `mean(str_detect(x, pattern))` tells you the proportion that match.
For example, the following snippet computes and visualizes the proportion of baby names[^regexps-4] that contain "x", broken down by year.
It looks like they've radically increased in popularity lately!
Podemos também usar a`str_detect()` com `summarize()` combinando-a com `sum()` ou `mean()`: `sum(str_detect(x, padrao))` informa o numero de observações correspondentes e `mean(str_detect(x, padrao))` informa a proporção da correspondência.
Por exemplo, o código a seguir, calcula e visualiza a proporção de nomes de bebês [^regexps-4] que contém "x", agrupados por ano.
Parece que eles aumentaram em popularidade ultimamente!

[^regexps-4]: This gives us the proportion of **names** that contain an "x"; if you wanted the proportion of babies with a name containing an x, you'd need to perform a weighted mean.
[^regexps-4]: Isto nos dá a proporção de **nomes** que contém um "x"; se você quiser a proporção de bebês com um nome contendo um x, você deveria usar uma média ponderada.

```{r}
#| fig-alt: |
#| A time series showing the proportion of baby names that contain the letter x.
#| The proportion declines gradually from 8 per 1000 in 1880 to 4 per 1000 in
#| 1980, then increases rapidly to 16 per 1000 in 2019.
babynames |>
group_by(year) |>
summarize(prop_x = mean(str_detect(name, "x"))) |>
ggplot(aes(x = year, y = prop_x)) +
bebes |>
group_by(ano) |>
summarize(prop_x = mean(str_detect(nome, "x"))) |>
ggplot(aes(x = ano, y = prop_x)) +
geom_line()
```

There are two functions that are closely related to `str_detect()`: `str_subset()` and `str_which()`.
`str_subset()` returns a character vector containing only the strings that match.
`str_which()` returns an integer vector giving the positions of the strings that match.
Existem duas funções que se relacionam muito com a `str_detect()`: `str_subset()` e `str_which()`.
`str_subset()` retorna um vetor de caractere contendo apenas as *strings* que correspondem ao padrão.
`str_which()` retorna um vetor de inteiro informando a posição das *strings* que correspondem ao padrão.

### Count matches
### Contando correspondências (*matches*)

The next step up in complexity from `str_detect()` is `str_count()`: rather than a true or false, it tells you how many matches there are in each string.
O próximo passo em complexidade de `str_detect()` é `str_count()`: em vez de verdadeiro (*true*) ou falso (*false*), ele informa quantas correspondências existem em cada *string*.

```{r}
x <- c("apple", "banana", "pear")
str_count(x, "p")
```

Note that each match starts at the end of the previous match, i.e. regex matches never overlap.
For example, in `"abababa"`, how many times will the pattern `"aba"` match?
Regular expressions say two, not three:
Note que cada correspondência começa ao final da anterior, e.x. regex nunca se sobrepõem.
Por exemplo, em `"abababa"`, quantas vezes o padrçao `"aba"` é correspondido?
A expressão regular dizem, duas, não três vezes:

```{r}
str_count("abababa", "aba")
str_view("abababa", "aba")
```

It's natural to use `str_count()` with `mutate()`.
The following example uses `str_count()` with character classes to count the number of vowels and consonants in each name.
É comum usar a `str_count()` com `mutate()`.
Os exemplos a seguir, usam `str_count()` com classes de caracteres para contar o número de vogais e consoantes em cada nome.

```{r}
babynames |>
count(name) |>
bebes |>
count(nome) |>
mutate(
vowels = str_count(name, "[aeiou]"),
consonants = str_count(name, "[^aeiou]")
vogais = str_count(nome, "[aeiou]"),
consoantes = str_count(nome, "[^aeiou]")
)
```

If you look closely, you'll notice that there's something off with our calculations: "Aaban" contains three "a"s, but our summary reports only two vowels.
That's because regular expressions are case sensitive.
There are three ways we could fix this:
Se você observar bem, você verá que há algo estranho em nossa contagem: "Aaban" contém três "a"s, mas nosso relatório sumarizado mostra apenas 2 vogais.
Isto é porque as expressões regulares consideram a diferença entre letras maiúsculas e minúsculas (*case sensitive*).
Existem três formas de arrumar isto:

- Add the upper case vowels to the character class: `str_count(name, "[aeiouAEIOU]")`.
- Tell the regular expression to ignore case: `str_count(name, regex("[aeiou]", ignore_case = TRUE))`. We'll talk about more in @sec-flags.
- Use `str_to_lower()` to convert the names to lower case: `str_count(str_to_lower(name), "[aeiou]")`.
- Adicionar as vogais maiúsculas nas classes de caracteres: `str_count(nome, "[aeiouAEIOU]")`.
- Informar a expressão regular para ignnorar esta diferença: `str_count(nome, regex("[aeiou]", ignore_case = TRUE))`. Falaremos mais sobre isto na @sec-flags.
- Usar a `str_to_lower()` para converter os nomes para letras minúsculas: `str_count(str_to_lower(nome), "[aeiou]")`.

This variety of approaches is pretty typical when working with strings --- there are often multiple ways to reach your goal, either by making your pattern more complicated or by doing some preprocessing on your string.
If you get stuck trying one approach, it can often be useful to switch gears and tackle the problem from a different perspective.
Esta variedade de abordagens é muito comum quando trabalhamos com *strings* --- em geral, há várias formas de atingir seus objetivos, seja formando padrões mais complexos ou efetuando algum pré-processamento em sua *string*.
Se você estiver bloqueado em uma abordagem, em geral, pode ser melhor mudar a marcha e atacar seu problema sob uma perspectiva diferente.

In this case, since we're applying two functions to the name, I think it's easier to transform it first:
Nesta caso, como estamos usando duas funções na variável nome, acredito ser mais fácil transformá-la antes:

```{r}
babynames |>
count(name) |>
bebes |>
count(nome) |>
mutate(
name = str_to_lower(name),
vowels = str_count(name, "[aeiou]"),
consonants = str_count(name, "[^aeiou]")
nome = str_to_lower(nome),
vogais = str_count(nome, "[aeiou]"),
consoantes = str_count(nome, "[^aeiou]")
)
```

### Replace values
### Trocando valores

As well as detecting and counting matches, we can also modify them with `str_replace()` and `str_replace_all()`.
`str_replace()` replaces the first match, and as the name suggests, `str_replace_all()` replaces all matches.
Assim como detectar e contar correspondências, você também pode modificá-las com `str_replace()` e `str_replace_all()`.
`str_replace()` troca a primeira correspondência e, como o nome pode sugerir, a `str_replace_all()` troca todas as correspondências.

```{r}
x <- c("apple", "pear", "banana")
str_replace_all(x, "[aeiou]", "-")
```

`str_remove()` and `str_remove_all()` are handy shortcuts for `str_replace(x, pattern, "")`:
`str_remove()` e `str_remove_all()` são funções atalhos para `str_replace(x, padrão, "")`:

```{r}
x <- c("apple", "pear", "banana")
str_remove_all(x, "[aeiou]")
```

These functions are naturally paired with `mutate()` when doing data cleaning, and you'll often apply them repeatedly to peel off layers of inconsistent formatting.
Estas funções combinam natualmente com `mutate()` quando fazemos limpeza de dados, e você geralmente as aplicará repetidamente para remover camadas de incosistência de formatação.

### Extract variables {#sec-extract-variables}
### Extraindo variáveis {#sec-extract-variables}

The last function we'll discuss uses regular expressions to extract data out of one column into one or more new columns: `separate_wider_regex()`.
It's a peer of the `separate_wider_position()` and `separate_wider_delim()` functions that you learned about in @sec-string-columns.
These functions live in tidyr because they operate on (columns of) data frames, rather than individual vectors.
A última função que discutiremos usa expressões regulares para extrair dados de uma coluna para um ou mais nova(s) coluna(s): `separate_wider_regex()`.
É uma função par da `separate_wider_position()` e `separate_wider_delim()` que você aprendeu na @sec-string-columns.
Estas funções estão no pacote tidyr pois elas operam em colunas de *data frames* ou invés de vetores individuais.

Let's create a simple dataset to show how it works.
Here we have some data derived from `babynames` where we have the name, gender, and age of a bunch of people in a rather weird format[^regexps-5]:
Vamos criar um conjunto simples de dados para mostrar como funciona.
Aqui temos alguns dados derivados de `dados::bebes` onde, temos nome, sexo biológico e idade de várias pessoas em um formato meio estranho[^regexps-5]:

[^regexps-5]: We wish we could reassure you that you'd never see something this weird in real life, but unfortunately over the course of your career you're likely to see much weirder!
[^regexps-5]: Gostaríamos de poder garantir que você nunca veria algo tão estranho na vida real, mas infelizmente, ao longo de sua carreira, é provável que você veja coisas muito mais estranhas!

```{r}
df <- tribble(
~str,
"<Sheryl>-F_34",
"<Kisha>-F_45",
"<Brandon>-N_33",
"<Brandon>-M_33",
"<Sharon>-F_38",
"<Penny>-F_58",
"<Justin>-M_41",
"<Patricia>-F_84",
)
```

To extract this data using `separate_wider_regex()` we just need to construct a sequence of regular expressions that match each piece.
If we want the contents of that piece to appear in the output, we give it a name:
Para extrair estes dados com `separate_wider_regex()`, precisamos apenas construir uma sequência de expressões regulares que correspondem a cada parte.
Se quisermos que o conteído de cada parte apareção na saída, damos um nome:

```{r}
df |>
separate_wider_regex(
str,
patterns = c(
"<",
name = "[A-Za-z]+",
nome = "[A-Za-z]+",
">-",
gender = ".",
sexo_biologico = ".",
"_",
age = "[0-9]+"
idade = "[0-9]+"
)
)
```

If the match fails, you can use `too_short = "debug"` to figure out what went wrong, just like `separate_wider_delim()` and `separate_wider_position()`.
Se a correpondência falhar, você pode usar `too_short = "debug"` para entender o que deu errado, assim como na `separate_wider_delim()` e `separate_wider_position()`.

### Exercises
### Exercícios

1. What baby name has the most vowels?
What name has the highest proportion of vowels?
(Hint: what is the denominator?)
1. Qual nome de bebê tem a menor quantidade de vogais?
QUal nome tem a maior proporção de vogais?
(Dica: qual o denominador?)

2. Replace all forward slashes in `"a/b/c/d/e"` with backslashes.
What happens if you attempt to undo the transformation by replacing all backslashes with forward slashes?
(We'll discuss the problem very soon.)
2. Troque todas as barras em `"a/b/c/d/e"` por barras invertidas.
O que acontece se você tentar desfazer esta mudança trocando as barras invertidas por barras?
(Discutiremos este problema em breve.)

3. Implement a simple version of `str_to_lower()` using `str_replace_all()`.
3. Implemente uma versão simples da `str_to_lower()` usando `str_replace_all()`.

4. Create a regular expression that will match telephone numbers as commonly written in your country.
4. Crie uma expressão regular para correpondências de números telefônicos da forma que são comumente escritas em seu país.

## Pattern details
## Detalhes de padrões

Now that you understand the basics of the pattern language and how to use it with some stringr and tidyr functions, it's time to dig into more of the details.
First, we'll start with **escaping**, which allows you to match metacharacters that would otherwise be treated specially.
Next, you'll learn about **anchors** which allow you to match the start or end of the string.
Then, you'll learn more about **character classes** and their shortcuts which allow you to match any character from a set.
Next, you'll learn the final details of **quantifiers** which control how many times a pattern can match.
Then, we have to cover the important (but complex) topic of **operator precedence** and parentheses.
And we'll finish off with some details of **grouping** components of the pattern.
Agora que você entende o básico da linguagem dos padrões e como usá-la com algumas funções do pacote stringr e tidyr, é hora de nos aprofundarmos mais nos detalhes.
Primeiro, começaremos com **escapadas** (*escaping*), que permite combinar metacaracteres que de outra forma seriam tratados de maneira especial.
A seguir, você aprenderá sobre **âncoras** (*anchors*) que permitem combinar com o início ou o fim da *string*.
Em seguida, você aprenderá mais sobre **classes de caracteres** (*character classes*) e seus atalhos que permitem combinar qualquer caractere de um conjunto.
A seguir, você aprenderá os detalhes finais dos **quantificadores** (*quantifiers*) que controlam quantas vezes um padrão pode corresponder.
Então, temos que cobrir o importante (mas complexo) tópico de **precedência de operador** (*operator precedence*) e parênteses.
E terminaremos com alguns detalhes de **agrupamento** (*grouping*) de componentes de um padrão.

The terms we use here are the technical names for each component.
They're not always the most evocative of their purpose, but it's very helpful to know the correct terms if you later want to Google for more details.
Os termos que usamos aqui são os nomes técnicos de cada componente.
Eles nem sempre são os que combinam melhor ao seu propósito, mas é muito útil saber os termos corretos se você quiser procurar mais detalhes no *Google* posteriormente.

### Escaping {#sec-regexp-escaping}
### Escapadas {#sec-regexp-escaping}

In order to match a literal `.`, you need an **escape** which tells the regular expression to match metacharacters[^regexps-6] literally.
Like strings, regexps use the backslash for escaping.
So, to match a `.`, you need the regexp `\.`. Unfortunately this creates a problem.
We use strings to represent regular expressions, and `\` is also used as an escape symbol in strings.
So to create the regular expression `\.` we need the string `"\\."`, as the following example shows.
Para correponder um `.` literal, você precisa **escapar**, o que informa a expressão regular para correponder ao metacaractere [^regexps-6] literalmente.
Assim como as *strings*, regexp usa a barra invertidade para escapadas (*escaping*).
Portanto, para corresponder a um `.`, você preacisa da regexp `\.`. Infelizmente isto cria um problema.
Nós usamos strings para representar expressões regulares, e `\` é também usada como símbolo de escapadas nas *strings*.
Portanto, para criar a expressão regular `\.` , precismos da *string* `"\\."`, como mostra os exemplos a seguir.

[^regexps-6]: The complete set of metacharacters is `.^$\|*+?{}[]()`
[^regexps-6]: A lista completa de metacaractere é `.^$\|*+?{}[]()`

```{r}
# To create the regular expression \., we need to use \\.
dot <- "\\."
# Para criar a expressão regular \., precisamos usar \\.
ponto <- "\\."
# But the expression itself only contains one \
str_view(dot)
# Mas a expressão regular em si, contém apenas uma \
str_view(ponto)
# And this tells R to look for an explicit .
# E isto diz ao R para procurar por um . explicitamente.
str_view(c("abc", "a.c", "bef"), "a\\.c")
```

In this book, we'll usually write regular expression without quotes, like `\.`.
If we need to emphasize what you'll actually type, we'll surround it with quotes and add extra escapes, like `"\\."`.

If `\` is used as an escape character in regular expressions, how do you match a literal `\`?
Well, you need to escape it, creating the regular expression `\\`.
To create that regular expression, you need to use a string, which also needs to escape `\`.
That means to match a literal `\` you need to write `"\\\\"` --- you need four backslashes to match one!
Neste livro, normalmente escreveremos expressões regulares sem aspas, como `\.`.
Se precisarmos enfatizar o que você realmente digitará, colocaremos aspas e adicionaremos escapadas extras, como `"\\."`.
Para criar essa expressão regular, você precisa usar uma string, que também precisa escapar de `\`.
Isso significa que para corresponder a um `\` literal você precisa escrever `"\\\\"` --- você precisa de quatro barras invertidas para corresponder a uma!

```{r}
x <- "a\\b"
@@ -338,92 +338,92 @@ That lets you avoid one layer of escaping:
str_view(x, r"{\\}")
```

If you're trying to match a literal `.`, `$`, `|`, `*`, `+`, `?`, `{`, `}`, `(`, `)`, there's an alternative to using a backslash escape: you can use a character class: `[.]`, `[$]`, `[|]`, \...
all match the literal values.
Se você está tentando correponder um `.`, `$`, `|`, `*`, `+`, `?`, `{`, `}`, `(`, `)` literal, há uma alternativa para não usar a escapada com barra invertida: você pode usar uma classe de caractere: `[.]`, `[$]`, `[|]`, \...
todas correspondem aos valores literais.

```{r}
str_view(c("abc", "a.c", "a*c", "a c"), "a[.]c")
str_view(c("abc", "a.c", "a*c", "a c"), ".[*]c")
```

### Anchors
### Âncoras

By default, regular expressions will match any part of a string.
If you want to match at the start or end you need to **anchor** the regular expression using `^` to match the start or `$` to match the end:
Por padrão, as expressões regulares corresponderão a qualquer parte de uma string.
Se você quiser corresponder no início ou no final, você precisa **ancorar** a expressão regular usando `^` para corresponder ao início ou `$` para corresponder ao final:

```{r}
str_view(fruit, "^a")
str_view(fruit, "a$")
```

It's tempting to think that `$` should match the start of a string, because that's how we write dollar amounts, but that's not what regular expressions want.
É tentador pensar que `$` deve corresponder ao início de uma string, porque é assim que escrevemos valores monetários, mas não é isso que as expressões regulares desejam.

To force a regular expression to match only the full string, anchor it with both `^` and `$`:
Para forçar uma expressão regular a corresponder apenas à string completa, ancore-a com `^` e `$`:

```{r}
str_view(fruit, "apple")
str_view(fruit, "^apple$")
```

You can also match the boundary between words (i.e. the start or end of a word) with `\b`.
This can be particularly useful when using RStudio's find and replace tool.
For example, if to find all uses of `sum()`, you can search for `\bsum\b` to avoid matching `summarize`, `summary`, `rowsum` and so on:
Você também pode combinar o limite entre as palavras (ou seja, o início ou o fim de uma palavra) com `\b`.
Isso pode ser particularmente útil ao usar a ferramenta localizar e substituir do RStudio.
Por exemplo, se quiser encontrar todos os usos de `sum()`, você pode procurar por `\bsum\b` para evitar a correspondência de `summarize`, `summary`, `rowsum` e assim por diante:

```{r}
x <- c("summary(x)", "summarize(df)", "rowsum(x)", "sum(x)")
str_view(x, "sum")
str_view(x, "\\bsum\\b")
```

When used alone, anchors will produce a zero-width match:
Quando usadas sozinhas, as âncoras produzirão uma correspondência de largura-zero (*zero-width*):

```{r}
str_view("abc", c("$", "^", "\\b"))
```

This helps you understand what happens when you replace a standalone anchor:
Isso ajuda você a entender o que acontece quando você substitui uma âncora independente:

```{r}
str_replace_all("abc", c("$", "^", "\\b"), "--")
```

### Character classes
### Classes de caracteres

A **character class**, or character **set**, allows you to match any character in a set.
As we discussed above, you can construct your own sets with `[]`, where `[abc]` matches "a", "b", or "c" and `[^abc]` matches any character except "a", "b", or "c".
Apart from `^` there are two other characters that have special meaning inside of `[]:`
Uma **classe de caracteres** (*character class*), ou um **conjunto** de caracteres, permite que você faça a correspondência de qualquer caractere deste conjunto.
Como discutido acima, você pode construir seus próprios conjuntos com `[]`, onde `[abc]` correponde a "a", "b" ou "c" e `[^abc]` corresponde a qualquer caractere exceto "a", "b" ou "c".
Além do `^` existem outros dois caracteres com significados especiais quando estão dentro de `[]:`

- `-` defines a range, e.g., `[a-z]` matches any lower case letter and `[0-9]` matches any number.
- `\` escapes special characters, so `[\^\-\]]` matches `^`, `-`, or `]`.
- `-` define um intervalo (*range*), e.x., `[a-z]` corresponde a qualquer letra minúscula e `[0-9]` a qualquer número.
- `\` caracteres especiais de escapadas, então `[\^\-\]]` corresponde `^`, `-` ou `]`.

Here are few examples:
Aqui estão alguns exemplos:

```{r}
x <- "abcd ABCD 12345 -!@#%."
str_view(x, "[abc]+")
str_view(x, "[a-z]+")
str_view(x, "[^a-z0-9]+")
# You need an escape to match characters that are otherwise
# special inside of []
# Você precisa de uma escapada para caracteres especiais
# dentro de []
str_view("a-b-c", "[a-c]")
str_view("a-b-c", "[a\\-c]")
```

Some character classes are used so commonly that they get their own shortcut.
You've already seen `.`, which matches any character apart from a newline.
There are three other particularly useful pairs[^regexps-7]:
Algumas classes de caracteres são tão comuns que possuem atalhos próprios.
Você já viu `.`, que corresponde a qualquer caractere exceto o de nova linha.
Existem três outras classes que são particularmente úteis[^regexps-7]:

[^regexps-7]: Remember, to create a regular expression containing `\d` or `\s`, you'll need to escape the `\` for the string, so you'll type `"\\d"` or `"\\s"`.
[^regexps-7]: Lembre-se, para criar uma expressão regular contendo `\d` ou `\s`, você precisará escapar a `\` da *string*, então você digitará `"\\d"` ou `"\\s"`.

- `\d` matches any digit;\
`\D` matches anything that isn't a digit.
- `\s` matches any whitespace (e.g., space, tab, newline);\
`\S` matches anything that isn't whitespace.
- `\w` matches any "word" character, i.e. letters and numbers;\
`\W` matches any "non-word" character.
- `\d` corresponde a qualquer digito;\
`\D` corresponde a qualquer coisa que não seja um digito.
- `\s` corresponde a qualquer espaço em branco (e.x., espaço, tab, nova linha);\
`\S` corresponde a qualquer coisa que não seja um espaço em branco.
- `\w` corresponde a qualquer caractere de "palavra" (*word*) , e.x. letras e números;\
`\W` corresponde a qualquer caractere de "não-palavra" (*non-word*).

The following code demonstrates the six shortcuts with a selection of letters, numbers, and punctuation characters.
O código a seguir demonstra os seis atalhos com a seleção de letras, números e caracteres de pontuação.

```{r}
x <- "abcd ABCD 12345 -!@#%."
@@ -435,61 +435,61 @@ str_view(x, "\\w+")
str_view(x, "\\W+")
```

### Quantifiers {#sec-quantifiers}
### Quantificadores {#sec-quantifiers}

**Quantifiers** control how many times a pattern matches.
In @sec-reg-basics you learned about `?` (0 or 1 matches), `+` (1 or more matches), and `*` (0 or more matches).
For example, `colou?r` will match American or British spelling, `\d+` will match one or more digits, and `\s?` will optionally match a single item of whitespace.
You can also specify the number of matches precisely with `{}`:
**Quantificadores** (*Quantifies*) controlam quantas vezes um padrão é correspondido.
Na @sec-reg-basics você aprendeu sobre o `?` (0 ou 1 correspondência), `+` (1 ou mais correspondência) e `*` (0 ou mais correspondências).
Por exemplo, `colou?r` irá corresponder à escrita em inglês estadunidense (*color*) e britânico (*colour*), `\d+` irá corresponder a um ou mais digitos, e `\s?` irá opcionalmente corresponder a um único espaço em branco.
Você também pode especificar o número exato de correspondências com `{}`:

- `{n}` matches exactly n times.
- `{n,}` matches at least n times.
- `{n,m}` matches between n and m times.
- `{n}` corresponde exatamente n vezes.
- `{n,}` corresponde ao menos n vezes.
- `{n,m}` corresponde entre n e m vezes.

### Operator precedence and parentheses
### Precedência de operadores e parênteses

What does `ab+` match?
Does it match "a" followed by one or more "b"s, or does it match "ab" repeated any number of times?
What does `^a|b$` match?
Does it match the complete string a or the complete string b, or does it match a string starting with a or a string ending with b?
Ao que `ab+` corresponde?
Corresponde a um "a" seguido por um ou mais "b"s, ou corresponde a "ab" repetidos qualquer número de vezes?
Ao que corresponde `^a|b$`?
Corresponde a uma *string* a completa OU um *string* b, ou a uma *string* que começa com a OU uma *string* que termina com b?

The answer to these questions is determined by operator precedence, similar to the PEMDAS or BEDMAS rules you might have learned in school.
You know that `a + b * c` is equivalent to `a + (b * c)` not `(a + b) * c` because `*` has higher precedence and `+` has lower precedence: you compute `*` before `+`.
As respostas para estas perguntas são determinadas pela precedência de operadores, similar a regras PEMDAS ou BEDMAS que você deve ter aprendido na escola.
Você sabe que `a + b * c` é equivalente a `a + (b * c)` e não `(a + b) * c` pois `*` tem uma prioridade mais alta de precedência e `+` tem uma precedência mais baixa: você calcula o `*` antes do `+`.

Similarly, regular expressions have their own precedence rules: quantifiers have high precedence and alternation has low precedence which means that `ab+` is equivalent to `a(b+)`, and `^a|b$` is equivalent to `(^a)|(b$)`.
Just like with algebra, you can use parentheses to override the usual order.
But unlike algebra you're unlikely to remember the precedence rules for regexes, so feel free to use parentheses liberally.
Da mesma forma, expressões regulares têm suas próprias regras de precedência: quantificadores têm precedência alta e alternância têm precedência baixa, o que significa que `ab+` é equivalente a `a(b+)`, e `^a|b$` é equivalente a `(^a )|(b$)`.
Assim como na álgebra, você pode usar parênteses para substituir a ordem normal.
Mas, diferentemente da álgebra, é improvável que você se lembre das regras de precedência para expressões regulares, então sinta-se à vontade para usar parênteses livremente..

### Grouping and capturing
### Agrupando e capturando

As well as overriding operator precedence, parentheses have another important effect: they create **capturing groups** that allow you to use sub-components of the match.
Além de substituir a precedência do operador, os parênteses têm outro efeito importante: eles criam **grupos de captura** que permitem usar subcomponentes da correspondência.

The first way to use a capturing group is to refer back to it within a match with **back reference**: `\1` refers to the match contained in the first parenthesis, `\2` in the second parenthesis, and so on.
For example, the following pattern finds all fruits that have a repeated pair of letters:
A primeira maneira de usar um grupo de captura é fazer referência a ele dentro de uma correspondência com **referência anterior**: `\1` refere-se à correspondência contida no primeiro parêntese, `\2` no segundo parêntese, e assim sobre.
Por exemplo, o padrão a seguir encontra todas as frutas que possuem um par de letras repetido:

```{r}
str_view(fruit, "(..)\\1")
```

And this one finds all words that start and end with the same pair of letters:
E este encontra todas as palavras que começam e terminam com o mesmo par de letras:

```{r}
str_view(words, "^(..).*\\1$")
```

You can also use back references in `str_replace()`.
For example, this code switches the order of the second and third words in `sentences`:
Você também pode usar referências anteriores (*back references*) em `str_replace()`.
Por exemplo, este código muda a ordem da segunda e terceira palavras em `sentences`:

```{r}
sentences |>
str_replace("(\\w+) (\\w+) (\\w+)", "\\1 \\3 \\2") |>
str_view()
```

If you want to extract the matches for each group you can use `str_match()`.
But `str_match()` returns a matrix, so it's not particularly easy to work with[^regexps-8]:
Se você deseja extrair as correspondências de cada grupo você pode usar `str_match()`.
Mas `str_match()` retorna uma matriz, então não é particularmente fácil trabalhar com ela[^regexps-8]:

[^regexps-8]: Mostly because we never discuss matrices in this book!
[^regexps-8]: Principalmente porque nunca discutimos sobre matrizes neste livro!

```{r}
sentences |>
@@ -503,45 +503,45 @@ You could convert to a tibble and name the columns:
sentences |>
str_match("the (\\w+) (\\w+)") |>
as_tibble(.name_repair = "minimal") |>
set_names("match", "word1", "word2")
set_names("correspondencia", "palavra1", "palavra2")
```

But then you've basically recreated your own version of `separate_wider_regex()`.
Indeed, behind the scenes, `separate_wider_regex()` converts your vector of patterns to a single regex that uses grouping to capture the named components.
Mas então você basicamente recriou sua própria versão de `separate_wider_regex()`.
Na verdade, nos bastidores, `separate_wider_regex()` converte seu vetor de padrões em um único regex que usa agrupamento para capturar os componentes nomeados.

Occasionally, you'll want to use parentheses without creating matching groups.
You can create a non-capturing group with `(?:)`.
Ocasionalmente, você desejará usar parênteses sem criar grupos correspondentes.
Você pode criar um grupo sem captura com `(?:)`.

```{r}
x <- c("a gray cat", "a grey dog")
str_match(x, "gr(e|a)y")
str_match(x, "gr(?:e|a)y")
x <- c("uma gata faminta", "um cão faminto")
str_match(x, "famint(o|a)")
str_match(x, "famint(?:o|a)")
```

### Exercises
### Exercícios

1. How would you match the literal string `"'\`? How about `"$^$"`?
1. Como você faria para corresponder a *string* literal `"'\`? E a `"$^$"`?

2. Explain why each of these patterns don't match a `\`: `"\"`, `"\\"`, `"\\\"`.
2. Explique porque cada um desses padrões não correspondem a `\`: `"\"`, `"\\"`, `"\\\"`.

3. Given the corpus of common words in `stringr::words`, create regular expressions that find all words that:
3. Dado o conjunto de palavras comuns em `stringr::words`, crie expressões regulares para encontrar todas as palavras que:

a. Start with "y".
b. Don't start with "y".
c. End with "x".
d. Are exactly three letters long. (Don't cheat by using `str_length()`!)
e. Have seven letters or more.
f. Contain a vowel-consonant pair.
g. Contain at least two vowel-consonant pairs in a row.
h. Only consist of repeated vowel-consonant pairs.
a. Comecem com "y".
b. Não comecem com um "y".
c. Terminem com "x".
d. Possuem exatamente três letras. (Não trapaceie usando a `str_length()`!)
e. Possuem sete letras ou mais.
f. Contém um par consoante-vogal.
g. Contém ao menos um par consoante-vogal em sequência.
h. É formada apenas por pares repetidos de consoantes-vogais.

4. Create 11 regular expressions that match the British or American spellings for each of the following words: airplane/aeroplane, aluminum/aluminium, analog/analogue, ass/arse, center/centre, defense/defence, donut/doughnut, gray/grey, modeling/modelling, skeptic/sceptic, summarize/summarise.
Try and make the shortest possible regex!
4. Crie 11 expressões regulares que correspondem a ortografias estadunidenses e britânicas para cada uma das seguintes palavras: airplane/aeroplane, aluminum/aluminium, analog/analogue, ass/arse, center/centre, defense/defence, donut/doughnut, gray/grey, modeling/modelling, skeptic/sceptic, summarize/summarise.
Tente e crie a menor expressão regular possível!

5. Switch the first and last letters in `words`.
Which of those strings are still `words`?
5. Troque a primeira e última letra em `words`.
Quais desses *strings* ainda são `palavras`?

6. Describe in words what these regular expressions match: (read carefully to see if each entry is a regular expression or a string that defines a regular expression.)
6. Descreva em palavras ao que correspondem as expressões abaixo: (leia com atenção para ver se cada parte corresponde a uma expressão regular ou a uma *string* que define uma expressão regular.)

a. `^.*$`
b. `"\\{.+\\}"`
@@ -551,187 +551,187 @@ str_match(x, "gr(?:e|a)y")
f. `(.)\1\1`
g. `"(..)\\1"`

7. Solve the beginner regexp crosswords at <https://regexcrossword.com/challenges/beginner>.
7. Resolva a palavra-cruzada de regex para iniciantes em <https://regexcrossword.com/challenges/beginner>.

## Pattern control
## Controle de padrões

It's possible to exercise extra control over the details of the match by using a pattern object instead of just a string.
This allows you to control the so called regex flags and match various types of fixed strings, as described below.
É possível exercer controle extra sobre os detalhes da correspondência usando um objeto padrão em vez de apenas uma string.
Isto permite que você controle os chamados sinalizadores (*flgas*) regex e combine vários tipos de strings fixas, conforme descrito abaixo.

### Regex flags {#sec-flags}
### Sinalizadores regex {#sec-flags}

There are a number of settings that can be used to control the details of the regexp.
These settings are often called **flags** in other programming languages.
In stringr, you can use these by wrapping the pattern in a call to `regex()`.
The most useful flag is probably `ignore_case = TRUE` because it allows characters to match either their uppercase or lowercase forms:
Existem várias configurações que podem ser usadas para controlar os detalhes do regexp.
Essas configurações costumam ser chamadas de **sinalizadores** (*flgas*) em outras linguagens de programação.
No pacote stringr, você pode usá-los agrupando o padrão em uma chamada para `regex()`.
O sinalizador mais útil é provavelmente `ignore_case = TRUE` porque permite que os caracteres correspondam às suas formas maiúsculas ou minúsculas:

```{r}
bananas <- c("banana", "Banana", "BANANA")
str_view(bananas, "banana")
str_view(bananas, regex("banana", ignore_case = TRUE))
```

If you're doing a lot of work with multiline strings (i.e. strings that contain `\n`), `dotall`and `multiline` may also be useful:
Se você trabalha muito com *strings* multilinhas (ou seja, *strings* que contêm `\n`), `dotall` e `multiline` também podem ser úteis:

- `dotall = TRUE` lets `.` match everything, including `\n`:
- `dotall = TRUE` faz com que o `.` corresponda a qualquer coisa, incluindo o `\n`:

```{r}
x <- "Line 1\nLine 2\nLine 3"
str_view(x, ".Line")
str_view(x, regex(".Line", dotall = TRUE))
x <- "Linha 1\nLinha 2\nLinha 3"
str_view(x, ".Linha")
str_view(x, regex(".Linha", dotall = TRUE))
```
- `multiline = TRUE` makes `^` and `$` match the start and end of each line rather than the start and end of the complete string:
- `multiline = TRUE` faz o `^` e o `$` corresponder ao início e fim de cada linha ao invés de do início e fim de cada *string* completa:
```{r}
x <- "Line 1\nLine 2\nLine 3"
str_view(x, "^Line")
str_view(x, regex("^Line", multiline = TRUE))
x <- "Linha 1\nLinha 2\nLinha 3"
str_view(x, "^Linha")
str_view(x, regex("^Linha", multiline = TRUE))
```
Finally, if you're writing a complicated regular expression and you're worried you might not understand it in the future, you might try `comments = TRUE`.
It tweaks the pattern language to ignore spaces and new lines, as well as everything after `#`.
This allows you to use comments and whitespace to make complex regular expressions more understandable[^regexps-9], as in the following example:
Finalmente, se você estiver escrevendo uma expressão regular complicada e estiver preocupado em não entendê-la no futuro, você pode tentar `comments = TRUE`.
Ele ajusta a linguagem padrão para ignorar espaços e novas linhas, bem como tudo depois de `#`.
Isso permite que você use comentários e espaços em branco para tornar expressões regulares complexas mais compreensíveis[^regexps-9], como no exemplo a seguir:
[^regexps-9]: `comments = TRUE` is particularly effective in combination with a raw string, as we use here.
[^regexps-9]: `comments = TRUE` é particularmente eficaz em combinação com uma string bruta (*raw*), como usamos aqui.
```{r}
phone <- regex(
telefone <- regex(
r"(
\(? # optional opening parens
(\d{3}) # area code
[)\-]? # optional closing parens or dash
\ ? # optional space
(\d{3}) # another three numbers
[\ -]? # optional space or dash
(\d{4}) # four more numbers
\(? # opcional abertura de parantese
(\d{3}) # codigo de area
[)\-]? # opcional fechamento de parantese ou traço
\ ? # opcional espaço
(\d{3}) # outros três números
[\ -]? # opcional espaço ou traço
(\d{4}) # quatro outros números
)",
comments = TRUE
)
str_extract(c("514-791-8141", "(123) 456 7890", "123456"), phone)
str_extract(c("514-791-8141", "(123) 456 7890", "123456"), telefone)
```

If you're using comments and want to match a space, newline, or `#`, you'll need to escape it with `\`.
Se você estiver usando comentários e quiser corresponder a um espaço, nova linha ou `#`, você precisará escapar usando a `\`.

### Fixed matches
### Correspondências fixas

You can opt-out of the regular expression rules by using `fixed()`:
Você pode optar por cancelar as regras de expressão regular usando `fixed()`:

```{r}
str_view(c("", "a", "."), fixed("."))
```

`fixed()` also gives you the ability to ignore case:
`fixed()` também te dá a habilidate de ignorar formas maiúsculas e minúsculas:

```{r}
str_view("x X", "X")
str_view("x X", fixed("X", ignore_case = TRUE))
```

If you're working with non-English text, you will probably want `coll()` instead of `fixed()`, as it implements the full rules for capitalization as used by the `locale` you specify.
See @sec-other-languages for more details on locales.
Se você estiver trabalhando com textos que não estão em Inglês, você provavelmente irá querer usar a `coll()` ao invés da `fixed()`, uma vez que ela implementa todas as regras de capitalização (*capitalization*) usadas pela `localização` (*locale*) que você especificou.
Veja a @sec-other-languages para maiores detalhes sobre localização.

```{r}
str_view("i İ ı I", fixed("İ", ignore_case = TRUE))
str_view("i İ ı I", coll("İ", ignore_case = TRUE, locale = "tr"))
```

## Practice
## Prática

To put these ideas into practice we'll solve a few semi-authentic problems next.
We'll discuss three general techniques:
Para colocar essas ideias em prática, resolveremos a seguir alguns problemas semi-autênticos.
Discutiremos três técnicas gerais:

1. checking your work by creating simple positive and negative controls
2. combining regular expressions with Boolean algebra
3. creating complex patterns using string manipulation
1. verificar seu trabalho criando controles simples positivos e negativos
2. combinando expressões regulares com álgebra booleana
3. criação de padrões complexos usando manipulação de *strings*

### Check your work
### Verifique seu trabalho

First, let's find all sentences that start with "The".
Using the `^` anchor alone is not enough:
Primeiro, vamos encontrar todas as frases que começam com “The.
Usar a âncora `^` por si só não é suficiente:

```{r}
str_view(sentences, "^The")
```

Because that pattern also matches sentences starting with words like `They` or `These`.
We need to make sure that the "e" is the last letter in the word, which we can do by adding a word boundary:
Porque esse padrão também corresponde a frases que começam com palavras como `They` ou `These`.
Precisamos ter certeza de que o “e” é a última letra da palavra, o que podemos fazer adicionando um limite (*boundary*) de palavra:

```{r}
str_view(sentences, "^The\\b")
```

What about finding all sentences that begin with a pronoun?
Que tal encontrar todas as frases que começam com um pronome?

```{r}
str_view(sentences, "^She|He|It|They\\b")
```

A quick inspection of the results shows that we're getting some spurious matches.
That's because we've forgotten to use parentheses:
Uma rápida inspeção dos resultados mostra que estamos obtendo algumas correspondências falsas.
Isso porque esquecemos de usar parênteses:

```{r}
str_view(sentences, "^(She|He|It|They)\\b")
```

You might wonder how you might spot such a mistake if it didn't occur in the first few matches.
A good technique is to create a few positive and negative matches and use them to test that your pattern works as expected:
Você deve estar se perguntando como identificar tal erro se ele não ocorreu nas primeiras correspondências.
Uma boa técnica é criar algumas correspondências positivas e negativas e usá-las para testar se o seu padrão funciona conforme o esperado:

```{r}
pos <- c("He is a boy", "She had a good time")
neg <- c("Shells come from the sea", "Hadley said 'It's a great day'")
pos <- c("Ele é jovem", "Elas se divertiram")
neg <- c("Eleitores não compareceram na data correta", "Hadley nos disse que é um bom dia!")
pattern <- "^(She|He|It|They)\\b"
str_detect(pos, pattern)
str_detect(neg, pattern)
padrao <- "^(Eu|Tu|Ele|Ela|Nós|Vós|Eles|Elas)\\b"
str_detect(pos, padrao)
str_detect(neg, padrao)
```

It's typically much easier to come up with good positive examples than negative examples, because it takes a while before you're good enough with regular expressions to predict where your weaknesses are.
Nevertheless, they're still useful: as you work on the problem you can slowly accumulate a collection of your mistakes, ensuring that you never make the same mistake twice.
Normalmente é muito mais fácil encontrar bons exemplos positivos do que negativos, porque leva um tempo até que você seja bom o suficiente com expressões regulares para prever onde estão seus pontos fracos.
No entanto, eles ainda são úteis: à medida que você trabalha no problema, você pode acumular lentamente uma coleção de seus erros, garantindo que nunca cometerá o mesmo erro duas vezes.

### Boolean operations {#sec-boolean-operations}
### Operações booleanas {#sec-boolean-operations}

Imagine we want to find words that only contain consonants.
One technique is to create a character class that contains all letters except for the vowels (`[^aeiou]`), then allow that to match any number of letters (`[^aeiou]+`), then force it to match the whole string by anchoring to the beginning and the end (`^[^aeiou]+$`):
Imagine que queremos encontrar palavras que contenham apenas consoantes.
Uma técnica é criar uma classe de caracteres que contenha todas as letras, exceto as vogais (`[^aeiou]`), então permitir que corresponda a qualquer número de letras (`[^aeiou]+`) e, em seguida, forçá-la a corresponder a *string* inteira ancorando no início e no final (`^[^aeiou]+$`):

```{r}
str_view(words, "^[^aeiou]+$")
```

But you can make this problem a bit easier by flipping the problem around.
Instead of looking for words that contain only consonants, we could look for words that don't contain any vowels:
Mas você pode tornar esse problema um pouco mais fácil invertendo-o.
Em vez de procurar palavras que contenham apenas consoantes, poderíamos procurar palavras que não contenham vogais:

```{r}
str_view(words[!str_detect(words, "[aeiou]")])
```

This is a useful technique whenever you're dealing with logical combinations, particularly those involving "and" or "not".
For example, imagine if you want to find all words that contain "a" and "b".
There's no "and" operator built in to regular expressions so we have to tackle it by looking for all words that contain an "a" followed by a "b", or a "b" followed by an "a":
Esta é uma técnica útil sempre que você estiver lidando com combinações lógicas, especialmente aquelas que envolvem “e” ou “não”.
Por exemplo, imagine se você deseja encontrar todas as palavras que contenham “a” e “b”.
Não há nenhum operador "e" embutido nas expressões regulares, então temos que resolver isso procurando todas as palavras que contenham um "a" seguido por um "b" ou um "b" seguido por um "a":

```{r}
str_view(words, "a.*b|b.*a")
```

It's simpler to combine the results of two calls to `str_detect()`:
É mais simples combinar os resultados de duas chamadas para `str_detect()`:

```{r}
words[str_detect(words, "a") & str_detect(words, "b")]
```

What if we wanted to see if there was a word that contains all vowels?
If we did it with patterns we'd need to generate 5!
(120) different patterns:
E se quiséssemos ver se existe uma palavra que contém todas as vogais?
Se fizéssemos isso com padrões precisaríamos gerar 5!
(120) padrões diferentes:

```{r}
#| results: false
#| resultado: falso
words[str_detect(words, "a.*e.*i.*o.*u")]
# ...
words[str_detect(words, "u.*o.*i.*e.*a")]
```

It's much simpler to combine five calls to `str_detect()`:
É muito mais simples combinar cinco chamadas para `str_detect()`:

```{r}
words[
@@ -743,129 +743,129 @@ words[
]
```

In general, if you get stuck trying to create a single regexp that solves your problem, take a step back and think if you could break the problem down into smaller pieces, solving each challenge before moving onto the next one.
Em geral, se você ficar preso tentando criar um único regexp que resolva seu problema, dê um passo para trás e pense se você poderia dividir o problema em partes menores, resolvendo cada desafio antes de passar para o próximo..

### Creating a pattern with code
### Criando um padrão com código

What if we wanted to find all `sentences` that mention a color?
The basic idea is simple: we just combine alternation with word boundaries.
E se quiséssemos encontrar todas as `sentences` que mencionam uma cor?
A ideia básica é simples: apenas combinamos alternância com limites de palavras (*boundary*).

```{r}
str_view(sentences, "\\b(red|green|blue)\\b")
```

But as the number of colors grows, it would quickly get tedious to construct this pattern by hand.
Wouldn't it be nice if we could store the colors in a vector?
Mas à medida que o número de cores aumenta, rapidamente se tornaria entediante construir esse padrão manualmente.
Não seria legal se pudéssemos armazenar as cores em um vetor?

```{r}
rgb <- c("red", "green", "blue")
```

Well, we can!
We'd just need to create the pattern from the vector using `str_c()` and `str_flatten()`:
Bem, nós podemos!
Precisaríamos apenas criar o padrão a partir do vetor usando `str_c()` e `str_flatten()`:

```{r}
str_c("\\b(", str_flatten(rgb, "|"), ")\\b")
```

We could make this pattern more comprehensive if we had a good list of colors.
One place we could start from is the list of built-in colors that R can use for plots:
Poderíamos tornar esse padrão mais abrangente se tivéssemos uma boa lista de cores.
Um lugar onde poderíamos começar é a lista de cores integradas que R usa para gerar gráficos:

```{r}
str_view(colors())
```

But lets first eliminate the numbered variants:
Mas vamos primeiro eliminar as variantes numeradas:

```{r}
cols <- colors()
cols <- cols[!str_detect(cols, "\\d")]
str_view(cols)
cores <- colors()
cores <- cores[!str_detect(cores, "\\d")]
str_view(cores)
```

Then we can turn this into one giant pattern.
We won't show the pattern here because it's huge, but you can see it working:
Então podemos transformar isso em um padrão gigante.
Não mostraremos o padrão aqui porque é enorme, mas você pode ver como ele funciona:

```{r}
pattern <- str_c("\\b(", str_flatten(cols, "|"), ")\\b")
str_view(sentences, pattern)
padrao <- str_c("\\b(", str_flatten(cores, "|"), ")\\b")
str_view(sentences, padrao)
```

In this example, `cols` only contains numbers and letters so you don't need to worry about metacharacters.
But in general, whenever you create patterns from existing strings it's wise to run them through `str_escape()` to ensure they match literally.
Neste exemplo, `cores` contém apenas números e letras, então você não precisa se preocupar com metacaracteres.
Mas, em geral, sempre que você criar padrões a partir de strings existentes, é aconselhável executá-los em `str_escape()` para garantir que eles correspondam literalmente.

### Exercises
### Exercícios

1. For each of the following challenges, try solving it by using both a single regular expression, and a combination of multiple `str_detect()` calls.
1. Para cada um dos desafios a seguir, tente resolvê-los usando uma única expressão regular e uma combinação de múltiplas chamadas `str_detect()`.

a. Find all `words` that start or end with `x`.
b. Find all `words` that start with a vowel and end with a consonant.
c. Are there any `words` that contain at least one of each different vowel?
a. Encontre todas as palavras em `words` que começam ou terminam com `x`.
b. Encontre todas as palavras em `words` que começam com vogal e terminam com consoante.
c. Existe alguma palavra em `words` que contenha pelo menos uma de cada vogal diferente?

2. Construct patterns to find evidence for and against the rule "i before e except after c"?
2. Construa padrões para encontrar evidências a favor e contra a regra "i antes de e exceto depois de c"?

3. `colors()` contains a number of modifiers like "lightgray" and "darkblue".
How could you automatically identify these modifiers?
(Think about how you might detect and then remove the colors that are modified).
3. `colors()` contém vários modificadores de cores como "lightgray" (cinza claro) e "darkblue" (azul escuro).
Como você poderia identificar automaticamente esses modificadores (light, dark) ?
(Pense em como você pode detectar e remover as cores modificadas).

4. Create a regular expression that finds any base R dataset.
You can get a list of these datasets via a special use of the `data()` function: `data(package = "datasets")$results[, "Item"]`.
Note that a number of old datasets are individual vectors; these contain the name of the grouping "data frame" in parentheses, so you'll need to strip those off.
4. Crie uma expressão regular que encontre qualquer conjunto de dados do R.
Você pode obter uma lista desses conjuntos de dados através do uso especial da função `data()`: `data(package = "datasets")$results[, "Item"]`.
Observe que vários conjuntos de dados antigos são vetores individuais; eles contêm o nome do "*data frame*" agrupado entre parênteses, então você precisará retirá-los.

## Regular expressions in other places
## Expressões regulares em outros lugares

Just like in the stringr and tidyr functions, there are many other places in R where you can use regular expressions.
The following sections describe some other useful functions in the wider tidyverse and base R.
Assim como nas funções stringr e tidyr, existem muitos outros lugares no R onde você pode usar expressões regulares.
As seções a seguir descrevem algumas outras funções úteis no tidyverse e no R base.

### tidyverse

There are three other particularly useful places where you might want to use a regular expressions
Existem três outros lugares particularmente úteis onde você pode querer usar expressões regulares

- `matches(pattern)` will select all variables whose name matches the supplied pattern.
It's a "tidyselect" function that you can use anywhere in any tidyverse function that selects variables (e.g., `select()`, `rename_with()` and `across()`).
- `matches(padrao)` selecionará todas as variáveis ​​cujo nome corresponda ao padrão fornecido.
É uma função "tidyselect" que você pode usar em qualquer lugar em qualquer função tidyverse que selecione variáveis ​​(por exemplo, `select()`, `rename_with()` e `across()`).

- `pivot_longer()'s` `names_pattern` argument takes a vector of regular expressions, just like `separate_wider_regex()`.
It's useful when extracting data out of variable names with a complex structure
- O argumento `names_pattern` da função `pivot_longer()` recebe um vetor de expressão regular, assim como na `separate_wider_regex()`.
É útil ao extrair dados de nomes de variáveis ​​com uma estrutura complexa

- The `delim` argument in `separate_longer_delim()` and `separate_wider_delim()` usually matches a fixed string, but you can use `regex()` to make it match a pattern.
This is useful, for example, if you want to match a comma that is optionally followed by a space, i.e. `regex(", ?")`.
- O argumento `delim` na `separate_longer_delim()` e na `separate_wider_delim()` geralmente corresponde a uma string fixa, mas você pode usar `regex()` para fazê-lo corresponder a um padrão.
Isso é útil, por exemplo, se você deseja corresponder uma vírgula que é opcionalmente seguida por um espaço, ou seja, `regex(", ?")`.

### Base R
### R base

`apropos(pattern)` searches all objects available from the global environment that match the given pattern.
This is useful if you can't quite remember the name of a function:
`apropos(padrao)` pesquisa todos os objetos disponíveis no ambiente global que correspondem ao padrão fornecido.
Isto é útil se você não consegue lembrar o nome de uma função:

```{r}
apropos("replace")
```

`list.files(path, pattern)` lists all files in `path` that match a regular expression `pattern`.
For example, you can find all the R Markdown files in the current directory with:
`list.files(caminho, padrao)` lista todos os arquivos em `caminho` que correspondem a uma expressão regular `padrao`.
Por exemplo, você pode encontrar todos os arquivos R Markdown no diretório atual com:

```{r}
head(list.files(pattern = "\\.Rmd$"))
```

It's worth noting that the pattern language used by base R is very slightly different to that used by stringr.
That's because stringr is built on top of the [stringi package](https://stringi.gagolewski.com), which is in turn built on top of the [ICU engine](https://unicode-org.github.io/icu/userguide/strings/regexp.html), whereas base R functions use either the [TRE engine](https://github.com/laurikari/tre) or the [PCRE engine](https://www.pcre.org), depending on whether or not you've set `perl = TRUE`.
Fortunately, the basics of regular expressions are so well established that you'll encounter few variations when working with the patterns you'll learn in this book.
You only need to be aware of the difference when you start to rely on advanced features like complex Unicode character ranges or special features that use the `(?…)` syntax.
É importante notar que a linguagem de padrão usada pelo R base é ligeiramente diferente daquela usada pelo stringr..
Isso ocorre porque stringr é construído sobre o [pacote stringi](https://stringi.gagolewski.com), que por sua vez é construído sobre o [mecanismo ICU](https://unicode-org.github.io /icu/userguide/strings/regexp.html), enquanto as funções base R usam o [mecanismo TRE](https://github.com/laurikari/tre) ou o [mecanismo PCRE](https://www.pcre .org), dependendo se você configurou ou não `perl = TRUE`.
Felizmente, os princípios básicos das expressões regulares estão tão bem estabelecidos que você encontrará poucas variações ao trabalhar com os padrões que aprenderá neste livro.
Você só precisa estar ciente da diferença quando começar a confiar em recursos avançados, como intervalos complexos de caracteres Unicode ou recursos especiais que usam a sintaxe `(?…)`.

## Summary
## Resumo

With every punctuation character potentially overloaded with meaning, regular expressions are one of the most compact languages out there.
They're definitely confusing at first but as you train your eyes to read them and your brain to understand them, you unlock a powerful skill that you can use in R and in many other places.
Com cada caractere de pontuação potencialmente sobrecarregado de significado, as expressões regulares são uma das linguagens mais compactas que existem.
Eles são definitivamente confusos no início, mas à medida que você treina seus olhos para lê-los e seu cérebro para entendê-los, você desbloqueia uma habilidade poderosa que pode ser usada em R e em muitos outros lugares.

In this chapter, you've started your journey to become a regular expression master by learning the most useful stringr functions and the most important components of the regular expression language.
And there are plenty of resources to learn more.
Neste capítulo, você iniciou sua jornada para se tornar um mestre em expressões regulares aprendendo as funções stringr mais úteis e os componentes mais importantes da linguagem de expressões regulares.
E ainda há muitos recursos para aprender mais.

A good place to start is `vignette("regular-expressions", package = "stringr")`: it documents the full set of syntax supported by stringr.
Another useful reference is [https://www.regular-expressions.info/](https://www.regular-expressions.info/tutorial.html).
It's not R specific, but you can use it to learn about the most advanced features of regexes and how they work under the hood.
Um bom lugar para começar é na `vignette("regular-expressions", package = "stringr")`: ela documenta o conjunto completo de sintaxe suportada pelo pacote stringr.
Outra referência útil é [https://www.regular-expressions.info/](https://www.regular-expressions.info/tutorial.html).
Não é específico do R, mas você pode usá-lo para aprender sobre os recursos mais avançados das expressões regulares e como elas funcionam.

It's also good to know that stringr is implemented on top of the stringi package by Marek Gagolewski.
If you're struggling to find a function that does what you need in stringr, don't be afraid to look in stringi.
You'll find stringi very easy to pick up because it follows many of the the same conventions as stringr.
Também é bom saber que stringr é implementado tendo o pacote stringi do Marek Gagolewski como base.
Se você está lutando para encontrar uma função que faça o que você precisa em stringr, não tenha medo de procurar no pacote stringi.
Você achará que stringi é muito fácil de aprender porque segue muitas das mesmas convenções que o stringr.

In the next chapter, we'll talk about a data structure closely related to strings: factors.
Factors are used to represent categorical data in R, i.e. data with a fixed and known set of possible values identified by a vector of strings.
No próximo capítulo, falaremos sobre uma estrutura de dados intimamente relacionada às *strings*: os fatores.
Fatores são usados ​​para representar dados categóricos em R, ou seja, dados com um conjunto fixo e conhecido de valores possíveis identificados por um vetor de *strings*.