Eu estava lendo recentemente na documentação do PCRE
– (expressões regulares compatíveis com Perl) e encontrei alguns truques interessantes com expressão regular. Enquanto continuei a ler e a me exaurir, parei por causa de alguma confusão em relação ao uso de alguns dos padrões (*...)
.
Minha dúvida e confusão está relacionada com (*PRUNE)
e (*FAIL)
Agora para referência (*SKIP)
age como (*PRUNE)
, exceto que se o padrão é desancorado, o avanço bumpalong não é para o próximo caractere, mas para a posição no assunto onde (*SKIP)
foi encontrado.
A documentação afirma que (*PRUNE)
faz com que a correspondência falhe na posição inicial atual no assunto, se o restante do padrão não corresponder. E ele declara (*FAIL)
sinônimo de afirmação negativa (?!)
. Força uma falha correspondente na posição determinada no padrão.
Então, basicamente (*FAIL)
se comporta como uma afirmação negativa falha e é sinônimo de (?!)
E (*PRUNE)
faz com que a correspondência falhe na posição inicial atual no assunto, se houver uma falha de correspondência posterior que faça com que o retrocesso o alcance.
Como estes são diferentes quando se trata de um ponto de falha?
Alguém pode fornecer exemplos de como eles são implementados e usados corretamente?
Antes de ler esta resposta, você deve estar familiarizado com o mecanismo de backtracking, grupos atômicos e quantificadores possessivos. Você pode encontrar informações sobre essas noções e resources no livro Friedl e seguindo estes links: http://www.regular-expressions.info , http://www.rexegg.com
Todo o teste foi feito com uma pesquisa global (com a function preg_match_all()
).
(*FALHOU)
baabo caaco daado caac(*FAIL)|aa.|caaco|co [0] => aab [1] => caaco [2] => aad
(*FAIL)
causa exatamente o mesmo comportamento que um “caractere ruim” em um padrão. Se você substitui por um “R” você obtém exatamente o mesmo resultado: caacR|aa.|caaco|co
. Para ser mais geral, você pode de fato replace (*FAIL)
por um “subpadrão sempre em falha” como: (?!)
, (?=a(? ...
a (first from "baabo")
: Sem surpresa, o primeiro resultado é encontrado pela segunda alternativa. ( aab
)
c (first)
: O motor regex encontra o primeiro "c" e tenta a primeira alternativa e encontra: caac
, mas o subpadrão é forçado a falhar. Em seguida, o mecanismo regex (sempre do primeiro "c") tenta a segunda alternativa que falha, a terceira alternativa é bem-sucedida. ( caaco
)
a (first from "daado")
: o terceiro resultado é encontrado pela segunda alternativa. ( aad
)
(*PULAR)
baabo caaco daado caa(*SKIP)c(*FAIL)|aa.|caaco|co [0] => aab [1] => co [2] => aad
Este verbo define um ponto além do qual o mecanismo regex não pode voltar atrás quando o subpadrão falha mais tarde. Conseqüentemente, todos os caracteres encontrados antes com o subpadrão são consumidos, de uma vez por todas , e não podem ser usados para outra parte do padrão (alternativa).
a (first from "baabo")
: o primeiro resultado é encontrado pela segunda alternativa. ( aab
)
c (first)
: o mecanismo regex encontra o caac
como no primeiro caso, depois falha (causa do verbo (*FAIL)
), retorna para o segundo "c", mas não é permitido voltar atrás aos caracteres que são correspondidos anteriormente (" caa ") antes do verbo (*SKIP)
.
c (second)
: Agora, o motor regex tenta sempre a primeira alternativa, mas nesta nova posição, e falha, pois há um "o" e não um "a" depois, então volta atrás para este segundo "c". Observe que, nesse caso, esses caracteres não são consumidos como anteriormente porque o subpadrão falhou antes de ter atingido o verbo (*SKIP)
. A segunda alternativa é testada e falha (não começa com um "c"). A terceira alternativa também falha porque o próximo caractere é um "o" e não um "a". A quarta alternativa é bem sucedida e dá o segundo resultado. ( co
)
a (first from "daado")
: o terceiro resultado é encontrado pela segunda alternativa. ( aad
)
(*AMEIXA SECA)
baabo caaco daado caa(*PRUNE)c(*FAIL)|aa.|caaco|co [0] => aab [1] => aac [2] => aad
Este verbo é diferente de (*SKIP)
porque não proíbe usar todos os caracteres anteriores combinados, mas pula o primeiro caractere correspondente pelo subpadrão (ou proíbe um subpadrão para começar) se o subpadrão falhar mais tarde.
a (first from "baabo")
: o primeiro resultado é encontrado pela segunda alternativa. ( aab
)
c (first)
: o motor regex encontra o caac
como no primeiro caso, depois falha, mas agora retrocede para o primeiro "a" de "caaco" desde que o primeiro "c" é ignorado.
a (first from "caaco")
: a primeira alternativa é tentada e falha, a segunda sucede e dá o segundo resultado. ( aac
)
a (first from "daado")
: o terceiro resultado é encontrado pela segunda alternativa. ( aad
)