Desempenho
Certos itens que podem aparecer nas expressões são mais eficientes que outros. É mais eficiente usar uma classe de caracteres como [aeiou] do que um conjunto de alternativas como (a|e|i|o|u). Em geral, a construção mais simples que proporciona o comportamento requerido é normalmente a mais eficiente. O livro de Jeffrey Friedl contém muita discussão sobre como otimizar expressões regulares para um desempenho eficiente.
Quando uma expressão começa com .* e a opção PCRE_DOTALL está
definida, a expressão é implicitamente ancorada pelo PCRE, pois ela
pode corresponder apenas ao início de um string de entrada. Porém, se
PCRE_DOTALL
não estiver definida, o PCRE não poderá fazer esta otimização,
pois o metacaractere . não corresponderá a uma nova linha
e, se a string de entrada contiver novas linhas, a expressão poderá
corresponder a partir do caractere imediatamente após um deles,
em vez de desde o início. Por exemplo, a expressão
(.*) second
corresponde à string "first\nand second" (onde \n representa
um caractere de nova linha) com a primeira substring capturada igual a
"and". Para fazer isso, o PCRE precisa tentar a correspondência novamente
iniciando após cada caractere de nova linha na string.
Se uma expressão como essa estiver sendo usada com uma string de entrada que não contêm novas linhas, o melhor desempenho será obtido definindo PCRE_DOTALL ou iniciando a expressão com ^.* para indicar ancoragem explícita. Isso evita que o PCRE tenha que varrer a string em busca de uma nova linha para reiniciar.
Cuidado com expressões que contêm repetições indefinidas aninhadas.
Elas podem levar muito tempo para serem executadas quando aplicados a uma string
que não corresponde. Considere o fragmento de expressão
(a+)*
Isso pode corresponder a "aaaa" de 33 maneiras diferentes, e esse número aumenta muito rapidamente à medida que a string fica mais longa. (A repetição * pode corresponder a 0, 1, 2, 3 ou 4 vezes e, para cada um desses casos diferentes de 0, as repetições + podem corresponder a diferentes números de vezes.) Quando o restante da expressão é tal que toda a correspondência irá falhar, o PCRE tem que, em princípio, tentar todas as variações possíveis, e isso pode levar muito tempo.
Uma otimização captura alguns dos casos mais simples
como
(a+)*b
,
onde um carectere literal aparece na sequência. Antes de embarcar no
procedimento padrão de correspondência, o PCRE verifica se existe um "b"
mais à frente na string de entrada, e se não houver, ele falha
a correspondência imediatamente. Porém, quando não há um caractere literal
na sequência, esta otimização não pode ser usada. Pode-se ver a
deferença comparando o comportamento de
(a+)*\d
com a expressão mais acima. A anterior falha quase
instantaneamente quando aplicada a uma linha inteira de caracteres "a",
enquanto que a última leva um tempo apreciável com strings
mais longas que aproximadamente 20 caracteres.