Regex Javascript trava (usando v8)

Estou usando esta regex para obter o conteúdo de uma tag em um arquivo.

var regex = new RegExp("((?:.|\\s)*)"); 

Isso faz com que o mecanismo v8 seja interrompido indefinidamente.

Agora, se eu usar o new RegExp("([\s\S]*)") , tudo é bom.

Alguém tem uma ideia de porque o primeiro demora muito?

Isso catastroficamente retrocede em longas seqüências de espaços que ocorrem após a última fechamento. Considere o caso em que a sequência de assunto termina com 100 espaços. Primeiro, combina todos eles com o . à esquerda da alternação. Isso falha porque não há tag de fechamento, então ele tenta igualar o último caractere com o \s . Isso também falha, então ele tenta igualar o segundo ao último espaço como um \s eo último espaço como um . . Isso falha (ainda não há tag de fechamento), então ele tenta o último espaço como um \s . Quando isso falha, ele combina o penúltimo espaço como um \s e tenta todas as 4 maneiras de combinar os dois últimos espaços. Quando isso falhar, ele tenta o penúltimo espaço como um \s e todas as 8 maneiras nos últimos 3 espaços. Então 16, 32 etc. O universo termina antes de chegar ao 100º ao último espaço.

VMs diferentes têm reações diferentes às correspondências de expressões regulares que levam uma eternidade por causa de um retrocesso catastrófico. Alguns irão simplesmente reportar “sem correspondência”. No V8 é como escrever qualquer outro loop infinito ou quase infinito.

O uso de non-greedy * fará o que você quiser (você quer parar no primeiro , não o último), mas ainda fará backtracking catastrófico para longas seqüências de espaços onde a sequência de fechamento está faltando.

Certificar-se de que os mesmos caracteres no colchete interno não correspondam a ambos os lados da alternância reduzirá o problema de um exponencial para um que seja linear no comprimento da cadeia. Use uma class de caractere em vez de uma alternação ou coloque \n no lado direito da barra de alternância. \n é disjunto . Então, se você acertar uma sequência longa de espaços, o mecanismo de expressão regular não tentará todas as combinações esquerda-direita-esquerda etc. antes de terminar.

Eu presumo que seja catastroficamente o rastreamento de volta.

Acho que parte do problema pode ser que o ponto e os pontos não sejam mutuamente exclusivos.

Se eu mudar sua expressão para

 ((?:.|[\r\n])*) 

e executá-lo no depurador Regex Buddy, ele falha muito mais rápido no caso em que a string de teste não é compatível.

Em vez de (?:.|\s)* , você pode usar [^]* para corresponder a qualquer caractere, incluindo várias formas de nova linha.

Não há alternância, portanto, nenhum risco de retrocesso catastrófico.