Melhores resultados de correspondência com String.prototype.matchAll()

Joe Medley
Joe Medley

O Chrome 73 introduz o método String.prototype.matchAll(). Ele se comporta de forma semelhante a match(), mas retorna um iterador com todas as correspondências de expressão regular em uma expressão regular global ou fixa. Isso oferece uma maneira simples de iterar correspondências, especialmente quando você precisa de acesso a grupos de captura.

O que há de errado com match()?

A resposta curta é nada, a menos que você esteja tentando retornar correspondências globais com grupos de captura. Aqui está um quebra-cabeça de programação para você. Considere o seguinte código:

const regex = /t(e)(st(\d?))/g;
const string = 'test1test2';
const results = string.match(regex);
console.log(results);
// → ['test1', 'test2']

Execute-o em um console. Ele retorna uma matriz contendo as strings 'test1' e 'test2'. Se eu remover a flag "g" da expressão regular, isso vai incluir todos os meus grupos de captura, mas só a primeira correspondência será exibida. Ela é assim:

['test1', 'e', 'st1', '2', index: 0, input: 'test1test2', groups: undefined]

Essa string contém uma segunda correspondência possível que começa com 'test2', mas ainda não a tenho. Aqui está o quebra-cabeça: como faço para conseguir todos os grupos de captura de cada correspondência? A explicação sobre a proposta String.prototype.matchAll() mostra duas abordagens possíveis. Não vou descrevê-las, porque espero que você não precise delas por muito mais tempo.

String.prototype.matchAll()

Como seriam os exemplos de explicação com matchAll()? Confira.

const regex = /t(e)(st(\d?))/g;
const string = 'test1test2';
const matches = string.matchAll(regex);
for (const match of matches) {
  console.log(match);
}

Há algumas coisas a serem observadas sobre isso. Ao contrário de match(), que retorna uma matriz em uma pesquisa global, matchAll() retorna um iterador que funciona muito bem com loops for...of. O iterador produz uma matriz para cada correspondência, incluindo os grupos de captura com alguns extras. Se você imprimi-los no console, eles ficarão assim:

['test1', 'e', 'st1', '1', index: 0, input: 'test1test2', groups: undefined]
['test2', 'e', 'st2', '2', index: 5, input: 'test1test2', groups: undefined]

O valor de cada correspondência é uma matriz exatamente no mesmo formato retornado por match() para expressões regulares não globais.

Material bônus

Isso é feito principalmente para pessoas que são novas nas expressões regulares ou que não são especialistas nelas. Talvez você tenha notado que os resultados de match() e matchAll() (para cada iteração) são matrizes com algumas outras propriedades nomeadas. Ao preparar este artigo, percebi que essas propriedades têm algumas deficiências de documentação no MDN (que corrigi). Aqui está uma descrição rápida.

index
O índice do primeiro resultado na string original. No exemplo acima, test2 começa na posição 5. Portanto, index tem o valor 5.
input
A string completa em que matchAll() foi executado. No meu exemplo, era 'test1test2'.
groups
Contém os resultados de todos os grupos de captura nomeados especificados na expressão regular.

Conclusão

Se isso acontecer, deixe um comentário abaixo. Saiba mais sobre as mudanças recentes no JavaScript nas atualizações anteriores ou no site do V8.