MiServe DevTools

Os seus autocolantes

Fixe aqui as ferramentas. Ficam guardadas neste navegador.

Testador de regex para JavaScript e Go (RE2)

Teste uma expressão regular no seu texto com o motor do JavaScript ou com o motor RE2 do Go, e veja cada correspondência, grupo de captura e substituição.

Flags

Correspondências no texto

Resumo da sintaxe dos dois motores
TokenSignificadoJavaScriptGo (RE2)
. Qualquer carácter exceto uma quebra de linha. Com a flag s, também corresponde a quebras de linha. Sim Sim
\d \w \s Um algarismo, um carácter de palavra, um carácter de espaço em branco. As maiúsculas \D, \W e \S correspondem ao contrário. Sim Sim
[abc] [^abc] [a-z] Um carácter de um conjunto, um carácter fora do conjunto, um carácter de um intervalo. Sim Sim
^ $ Início e fim do texto. Com a flag m, início e fim de cada linha. Sim Sim
\b \B Um limite de palavra, e uma posição que não é limite de palavra. Sim Sim
* + ? {2,5} Zero ou mais, uma ou mais, zero ou uma, entre 2 e 5 vezes. Cada um corresponde ao máximo possível. Sim Sim
*? +? ?? {2,5}? Os mesmos quantificadores, correspondendo ao mínimo possível. Sim Sim
(…) (?:…) Um grupo de captura, e um grupo que só agrupa. Sim Sim
(?<name>…) Um grupo de captura com nome. O Go aceita esta forma desde a versão 1.22, e (?P<name>…) em todas as versões. Sim Sim
a|b Ou a ou b. Sim Sim
\p{L} \p{Lu} Uma propriedade Unicode: qualquer letra, qualquer letra maiúscula. No JavaScript precisa da flag u. Sim Sim
(?i) (?s) (?m) Flags escritas dentro do padrão. No JavaScript, as flags definem-se fora dele. Não Sim
\A \z Início e fim do texto inteiro, independentemente da flag m. Não Sim
[[:alpha:]] Uma classe de caracteres POSIX dentro de um conjunto. Não Sim
(?=…) (?!…) Lookahead: o que se segue tem de corresponder, ou não pode corresponder, sem ser consumido. Sim Não
(?<=…) (?<!…) Lookbehind: o que vem antes tem de corresponder, ou não pode corresponder. Sim Não
\1 \k<name> Referência anterior (backreference): o mesmo texto a que um grupo anterior correspondeu. Sim Não

Funciona no seu navegador com WebAssembly. Nada do que cola é enviado.

Sobre esta ferramenta

Dois motores de duas famílias

Os motores de expressões regulares dividem-se em duas famílias. Os motores de backtracking, como o PCRE e os motores predefinidos do JavaScript, Python, Java e .NET, experimentam um caminho pelo padrão e recuam quando falha. É esse desenho que torna possíveis o lookahead, o lookbehind e as referências anteriores. Os motores de autómato, como o RE2 e o pacote regexp do Go, seguem todos os caminhos possíveis ao mesmo tempo, pelo que o tempo de execução cresce linearmente com o comprimento do texto. O preço é não terem lookaround nem referências anteriores.

O motor do JavaScript aqui é o próprio RegExp do seu navegador. O motor do Go é o pacote padrão regexp do Go compilado para WebAssembly, por isso o código que executa o seu padrão aqui é o mesmo que o executa num programa em Go. O Go aceita a sintaxe do RE2.

Ler os resultados

Cada correspondência é contornada e realçada no texto, em duas cores alternadas para que se distingam correspondências encostadas umas às outras. Uma correspondência vazia, como a que x* encontra entre duas letras, é desenhada como uma barra fina. A tabela indica o início e o fim de cada correspondência e o texto de cada grupo de captura. Um grupo que não participou numa correspondência é marcado como sem correspondência, o que é diferente de um grupo que correspondeu a uma string vazia.

As posições contam unidades de código UTF-16 a partir de zero, e o fim é exclusivo: são os números que passaria a String.prototype.slice em JavaScript. O Go devolve deslocamentos em bytes no texto UTF-8; a ferramenta converte-os, para que os dois motores mostrem os mesmos números.

Em JavaScript, um padrão sem a flag g encontra apenas a primeira correspondência e substitui apenas a primeira correspondência. O motor do Go devolve sempre todas as correspondências, tal como FindAllStringSubmatchIndex e ReplaceAllString.

Backtracking catastrófico

Um motor de backtracking pode precisar de tempo exponencial quando os quantificadores estão aninhados ou se sobrepõem. O caso clássico é (a+)+$ testado contra uma longa sequência de a seguida de outro carácter: o motor experimenta todas as formas de repartir a sequência entre o quantificador interior e o exterior antes de desistir. Num servidor, isto é um risco de negação de serviço conhecido como ReDoS.

Esta ferramenta executa os padrões de JavaScript num worker em segundo plano e para o worker ao fim de 1,5 segundos, para que a página continue a responder e lhe diga o que aconteceu. Testar o mesmo padrão com o motor do Go é uma forma rápida de ver se a lentidão vem do backtracking, porque o Go garante um tempo de execução linear no comprimento do texto.

Perguntas

Porque é que o meu padrão funciona em JavaScript mas falha em Go?

Uma causa comum é um lookahead, um lookbehind ou uma referência anterior, que o RE2 deixa de fora para poder garantir um tempo de execução linear. As flags são outra causa comum: o Go não tem flags fora do padrão, por isso a correspondência sem distinção de maiúsculas e minúsculas escreve-se com (?i) no início.

Em que diferem as strings de substituição entre JavaScript e Go?

Ambos usam $1 para o primeiro grupo. Um grupo com nome é $<name> em JavaScript e ${name} em Go. Em Go, $1x significa um grupo chamado 1x, por isso escreva ${1}x quando a referência é seguida de uma letra, um algarismo ou um underscore.

Posso testar aqui padrões de PCRE, Python ou Java?

Nesta página só funcionam os motores do JavaScript e do Go. A sintaxe do dia a dia é comum às várias variantes, por isso o motor do JavaScript é uma boa aproximação para padrões simples, mas funcionalidades como quantificadores possessivos, grupos atómicos e recursão não estão disponíveis em nenhum dos dois motores.

O texto que testo é enviado para um servidor?

Não. Os dois motores funcionam no seu navegador: o JavaScript num worker em segundo plano, o Go como módulo WebAssembly. A ferramenta não faz nenhum pedido de rede com o seu padrão nem com o seu texto, e a política de segurança do site bloqueia pedidos a qualquer outro servidor.

Mais ferramentas de Texto