Sintaxe de Expressões Regulares em JavaScript
Definição de Classes de Caracteres
Para definir expressões regulares, podemos usar classes de caracteres. As classes de caracteres são definidas usando colchetes:
[xyz]
(correspondência alternativa): corresponde a um dos caracteres: x, y ou z. É equivalente a x|y|z.[^xyz]
(negação): corresponde a qualquer caractere EXCETO x, y ou z.[a-zA-Z]
(intervalo): corresponde a qualquer caractere no intervalo de a-z ou A-Z.
Por exemplo, para verificar se um texto contém os caracteres "a", "b" ou "c":
const exp = /[abc]/; // corresponde a "a", "b" ou "c"
const str1 = "JavaScript";
const str2 = "Pascal";
const str3 = "Python";
console.log(exp.test(str1)); // true
console.log(exp.test(str2)); // true
console.log(exp.test(str3)); // false
A expressão [abc]
indica que a string deve conter uma das três letras mencionadas. A expressão [abc]
também é equivalente a a|b|c
.
Vamos a um exemplo mais prático. Suponha que temos códigos PIN de 4 dígitos e precisamos verificar se o código contém apenas dígitos:
const exp = /[0-9][0-9][0-9][0-9]/; // corresponde a quatro dígitos consecutivos
const code1 = "1234";
const code2 = "jav5";
const code3 = "3452";
console.log(exp.test(code1)); // true
console.log(exp.test(code2)); // false
console.log(exp.test(code3)); // true
A expressão [0-9][0-9][0-9][0-9]
corresponde a qualquer sequência de 4 dígitos consecutivos. Por exemplo, ela corresponde à string "3452", mas NÃO à string "jav5" (que contém apenas um dígito). A string "jav5" corresponderia ao padrão [a-z][a-z][a-z][0-9]
(três caracteres alfabéticos em minúsculas seguidos por um dígito).
Vale ressaltar que a expressão [0-9][0-9][0-9][0-9]
não é otimizada, e mais adiante veremos como simplificá-la.
Outro exemplo - utilizando negação:
const exp = /[^a-z]/; // corresponde a qualquer caractere, exceto letras de a-z
const code1 = "zorro";
const code2 = "zorro5";
const code3 = "34521";
console.log(exp.test(code1)); // false
console.log(exp.test(code2)); // true
console.log(exp.test(code3)); // true
Aqui, as strings são verificadas para corresponder à expressão [^a-z]
, que corresponde a qualquer caractere exceto os do intervalo de a-z. Por exemplo, a string "zorro" NÃO corresponde a esta expressão, mas "zorro5" corresponde, pois contém um caractere fora do intervalo "a-z".
Se necessário, podemos combinar expressões:
const exp = /[dt]o[nm]/; // corresponde às strings "dom", "tom", "don", "ton"
const str1 = "doma";
const str2 = "soma";
const str3 = "tona";
console.log(exp.test(str1)); // true
console.log(exp.test(str2)); // false
console.log(exp.test(str3)); // true
Nesse exemplo, a expressão regular [dt]o[nm]
verifica se a string contém "dom", "tom", "don", ou "ton".
Metacaracteres
Em vez de definir nossas próprias classes de caracteres, podemos usar as incorporadas, que também são chamadas de metacaracteres - símbolos que têm um significado específico:
\d
: corresponde a qualquer dígito de 0 a 9. Equivalente à expressão[0-9]
.\D
: corresponde a qualquer caractere que não seja um dígito. Equivalente à expressão[^0-9]
.\w
: corresponde a qualquer letra, dígito ou sublinhado (intervalos A-Z, a-z, 0-9). Equivalente à expressão[a-zA-Z_0-9]
.\W
: corresponde a qualquer caractere que não seja uma letra, dígito ou sublinhado (ou seja, não está nos intervalos A-Z, a-z, 0-9). Equivalente à expressão[^\w]
.\s
: corresponde a um espaço em branco. Equivalente à expressão[\t\n\x0B\f\r]
.\S
: corresponde a qualquer caractere que não seja um espaço em branco. Equivalente à expressão[^\s]
..
: corresponde a qualquer caractere.
É importante notar que o metacaractere \w é aplicável apenas para letras do alfabeto latino.
Por exemplo, para verificar que um código possui apenas 4 dígitos, usamos anteriormente a expressão /[0-9][0-9][0-9][0-9]/
. Podemos simplificar isso usando o metacaractere \d
:
const exp = /\d\d\d\d/; // corresponde a quatro dígitos consecutivos
const code1 = "1234";
const code2 = "jav5";
const code3 = "3452";
console.log(exp.test(code1)); // true
console.log(exp.test(code2)); // false
console.log(exp.test(code3)); // true
Outro exemplo: suponha que precisamos encontrar strings que contêm um número de telefone no formato +x-xxx-xxx-xxxx:
const exp = /\+\d-\d\d\d-\d\d\d-\d\d\d\d/;
const contact1 = "Email: mycomp@gmail.com";
const contact2 = "Phone: +1-234-567-8901";
console.log(exp.test(contact1)); // false
console.log(exp.test(contact2)); // true
Portanto, o número de telefone +1-234-567-8901 corresponde a /+\d-\d\d\d-\d\d\d-\d\d\d\d/.
+ | \d | - | \d | \d | \d | - | \d | \d | \d | - | \d | \d | \d | \d |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+ | 1 | - | 2 | 3 | 4 | - | 5 | 6 | 7 | - | 8 | 9 | 0 | 2 |
Note a barra antes do sinal de mais \+
. Como o sinal de mais tem um significado especial, para indicar que nos referimos ao sinal de mais como um caractere de string, colocamos uma barra antes dele.
Assim, na string "Phone: +1-234-567-8901", o método exp.test(contact2)
corresponderá à substring "+1-234-567-8901" no texto.
Limitando o Alcance de Expressões Regulares
Alguns caracteres especiais permitem limitar o alcance das expressões regulares:
^
: corresponde ao início da linha. Por exemplo,^h
corresponde à string "home", mas não a "ohma", pois o 'h' deve estar no início da linha.$
: corresponde ao fim da linha. Por exemplo,m$
corresponde à string "dom", porque a string deve terminar com a letra 'm'.\b
: corresponde ao início ou ao fim de uma palavra.\B
: ignora os limites de palavras.
Por exemplo, se precisamos encontrar strings com um número de telefone:
const exp = /\d{10}/; // corresponde a 10 dígitos consecutivos
const phone1 = "+12345678901";
const phone2 = "42345678901";
console.log(exp.test(phone1)); // true
console.log(exp.test(phone2)); // true
A expressão /\d{10}/
corresponde tanto à string "+12345678901" quanto à "42345678901". No entanto, se precisamos encontrar números de telefone que não são precedidos por um sinal de mais "+", podemos usar a expressão regular ^\d{10}
. Assim, a string corresponderá ao padrão se começar com caracteres numéricos:
const exp = /^\d{10}/; // corresponde a 10 dígitos consecutivos
const phone1 = "+12345678901";
const phone2 = "42345678901";
console.log(exp.test(phone1)); // false
console.log(exp.test(phone2)); // true
Outro exemplo: suponha que precisamos verificar se uma string menciona o idioma "Java". Uma abordagem ingênua seria usar a expressão regular /Java/
:
const exp = /Java/;
const str1 = "Java is a high-level, object-oriented programming language";
const str2 = "JavaScript is a programming language of the World Wide Web";
console.log(exp.test(str1)); // true
console.log(exp.test(str2)); // true
No entanto, na realidade, o padrão /Java/
corresponde a qualquer string que contenha a substring "Java", incluindo "JavaScript". Mas se precisamos encontrar apenas aquelas strings que se referem especificamente ao Java, e não ao JavaScript, podemos limitar a pesquisa aos limites das palavras usando \b
:
const exp = /Java\b/; //
const str1 = "Java is a high-level, object-oriented programming language";
const str2 = "JavaScript is a programming language of the World Wide Web";
console.log(exp.test(str1)); // true
console.log(exp.test(str2)); // false
O flag \B
, por outro lado, indica que o padrão deve corresponder a substrings que não são palavras completas:
const exp = /Java\B/;
const str1 = "Java is a high-level, object-oriented programming language";
const str2 = "JavaScript is a programming language of the World Wide Web";
console.log(exp.test(str1)); // false
console.log(exp.test(str2)); // true
Flags em Expressões Regulares
Os flags permitem ajustar o comportamento das expressões regulares. Cada flag é representado por um caractere específico que é colocado no final da expressão regular. Em JavaScript, os seguintes flags são usados:
Flag global (g)
: Permite encontrar todas as substrings que correspondem à expressão regular. Por padrão, uma expressão regular encontra a primeira substring correspondente em uma string. Se houver várias substrings que correspondem, o flagg
é usado para identificá-las.Flag ignoreCase (i)
: Permite encontrar substrings que correspondem à expressão regular, independentemente do case (maiúsculas ou minúsculas). Isso é feito usando o caracterei
nas expressões regulares.Flag multiline (m)
: Permite encontrar substrings que correspondem à expressão regular em um texto com várias linhas. Isso é feito usando o caracterem
nas expressões regulares.Flag dotAll (s)
: Permite que o caractere ponto (.
) em uma expressão regular corresponda a qualquer caractere, incluindo delimitadores de linha. Isso é feito usando o caracteres
nas expressões regulares.
O flag i (ignoreCase)
Exemplo:
const str = "Hello World";
const exp = /world/;
console.log(exp.test(str)); // false
// Usando o flag i para ignorar o case
const expWithIgnoreCase = /world/i;
console.log(expWithIgnoreCase.test(str)); // true
Note onde o flag é colocado na expressão regular: /world/i
— no final da expressão.
O flag s (dotAll)
Exemplo:
const str = "hello\nworld";
const exp = /hello world/;
console.log(exp.test(str)); // false
// Usando o flag s para que a expressão regular ignore o delimitador de linha
const expWithDotAll = /hello.world/s;
console.log(expWithDotAll.test(str)); // true
Neste exemplo, a expressão /hello.world/s
usa o ponto para representar qualquer caractere, permitindo que a expressão regular corresponda a texto multilinha.
Combinando flags:
É possível usar vários flags simultaneamente:
const str = "hello\nWorld";
const exp = /hello.world/is;
console.log(exp.test(str)); // true
Aqui, os flags s
e i
são combinados, permitindo que a expressão regular corresponda independentemente do delimitador de linha e do case das letras.