Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Bruno Augusto

[Resolvido] Fazer preg_match() trabalhar supostamente como ereg()

Recommended Posts

Que dia gloriosamente macabro para se encontrar um bug sinistro, não?

 

Pior, achei que me livraria dele <_<

 

Se eu entendi direito, a explicação está no item 3 dessa seção do manual, mas infelizmente não poss ter certeza pois na minha instalação, ereg() sequer roda.

 

Obviamente, não é a informação REAL, apenas um à parte para que eu possa trabalhar mais rapidamente na solução:

 

$ERs = array( '/',
             'main\b(.*?)',
             'translate\b(.*?)',
             'manager/actresses\b(.*?)',
             'manager/actresses/view\b(.*?)',
             'manager/actresses/add\b(.*?)',
             'manager/actresses/add/another/value/to/test/the/longest/match\b(.*?)' );

$input = 'manager/actresses/add/option/value';

foreach( $ERs as $ER ) {

   if( preg_match( sprintf( '@^%s@D', $ER ), $input ) ) {
       var_dump( $input, $ER ); break;
   }
}

Existe a matriz com algumas Expressões Regulares e existe um dado valor fixo.

 

As ER's são construídas por uma parte fixa (strings) e uma variável (grupo quantificador)

 

Rodando esse código, eu gostaria que preg_match() casasse todo o texto "visível" antes de operar sobre os metacaracteres. Mas ele está parando logo no primeiro resultado positivo, que é o esperado pela função:

 

...but PCRE stops on the first valid match

No exemplo, mesmo que a string passada posua adicionalmente /add, a verificação está parando no manager/actresses :pinch:

 

Como que eu faria esse casamento?

 

P.S.: Não poderiam ser listados todos os casamentos para se obter o maior deles pois como uso real será em uma função, de retorno condicionado ao casamento em si, dessa forma, haveria perdade perfomance proporcional ao número de Expressões.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Algumas dicas:

 

1 - Não há a necessidade do uso de "?" após um quantificador *, pois ele já torna o resultado opcional.

2 - Para ele capturar todos os resultados, troque sua função preg_match para preg_match_all.

 

Tem mais alguns detalhes que passei desapercebido, mas sei que tu tens experiência com ERs, quiçá mais que eu, e como tu mesmo disseste "Obviamente, não é a informação REAL, apenas um à parte para que eu possa trabalhar mais rapidamente na solução"...

 

Um abraço!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu aprendi, no Guia ER que, trocando em miúdos, o * é um fominha miserável :P

 

Mas assim, eu bem que pensei em usar preg_match_all(), mas caiu justamente na observação que pus no final.

 

Na situação REAL, essa lista de ER's pode pelo menos dobrar, mas tem potencial para até mesmo quadruplicar, já que por fazer parte de um roteador de URL's (ops, falei demais), uma mesma URL pode ser roteada para GET, POST, PUT...

 

Ao intenção não é casar todas as possibilidades e sim casar a maior quantidade de texto possível antes de o quantificador ser utilizado.

 

E como o retorno da função onde eu aplicarei o conceito do tópico teria de ser mais ou menos como:

 

return preg_match( '/.../', $text ) != 0

Se casar logo de cara, recebo a informação errada, já que cada ER é uma entrada com ID próprio e informações relacionadas próprias.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Nossa, complicadinho hein...

Pelo que entendi, você precisa fazer uma verificação da direita para a esquerda, é mais ou menos isso?

 

Acho que só com ER's não será possível, talvez tenhas que utilizar arrays, quebrando préviamente esses diretórios. Por exemplo:

 

1 - Explodir os diretórios.

2 - Contar a quantidade destes, e filtrar para a mesma quantidade de diretórios da base.

3 - Verificar em cima do último diretório, ou seja, o mais da direita.

 

Infelizmente não sei como te ajudar além dessas dicas..

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olhando por esse ângulo, sim.

 

Se houver outra forma mais simples, mesmo que precise mudar a forma de detecção, aceito de bom grado também.

 

Funciona que é uma beleza do jeito que está, desde que as ER's não colidam de nenhuma forma.

 

Acabei de pensar numa possibilidade, que seria na hora demontar essa matriz com a ER's, reordená-la alfabeticamente.

 

Pelo menos em teoria, isso faria com que as ER's maiores (mais específicas) ficassem mais em cima e as menores (mais genéricas) embaixo:

 

$ERs = array( 'manager/actresses/add/another/value/to/test/the/longest/match\b(.*?)', // Conflita           
             'manager/actresses/view\b(.*?)',
             'manager/actresses/add\b(.*?)',
             'manager/actresses\b(.*?)',
             'translate\b(.*?)',
             'main\b(.*?)',
             '/' );

Num teste preliminar, deu certo, estarsaber nas vias de fato se não vai dar problema.

 

Se você ou mais alguém vir algum possível problema e puder apontar, agradeço antecipadamente.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Testei mais a fundo e, por hora, tudo perfeito.

 

Mandei as Rotas de URL's mais longas para o topo e as mais curtas para o fim, assim a maior quantidade de texto é casada e, se não, casa na mais genérica.

 

Muito importante que quem mexe com ER's entenda essa diferença. No link do manual deixa bem claro que é por questões de performance, mas nesse caso pode ser (como foi) um terrível e inconveniente problema.

 

A quem interessar, tal ordenação foi feitas assim:

 

usort(

           $ERs,

           function( $a, $b ) {

               return ( strlen( $a < $b ) ? -1 : 1 );
           }
       );

Se estiver usando arrays multidimensionais, basta definir as dimensões em $a e $b dentro de strlen(). :thumbsup:

 

Muito obrigado por ter ao menos tentado ajudar Matheus ;) (só pra não repetir o smiley anterior :P )

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.