3
respostas

REGEX busca booleana

Boa tarde pessoal, estou tentando montar um REGEX para validar uma query de busca booleana (search boolean) onde os operadores aceitos são: "", (), AND, NOT, OR. Estou validando abertura e fechamento de aspas, mas também não sei se a melhor maneira, pois estou validando a abertura de qualquer um dos dois e fazendo um while nas aspas e um switch nos parenteses para validar se ambos os casos estão fechados.

Sendo validos os casos acima, tenho que verificar se a sintaxe está correta antes de fazer uma chamada para o backend (estou usando angular e validando no controller através do ng-change do input (também não sei se seria a melhor maneira, penso no futuro tirar para uma diretiva));

Exemplos válidos:

  • (programador AND estagiario) OR "analista de sistemas"
  • Analista de Sistemas AND NOT programador
  • NOT analista AND (NOT frontend AND backend) OR "fullstack"

Inválidos:

  • (programador ou analista)
  • (programador OR analista
  • "programador frontend AND analista OR NOT diretor

Bem, +- isso, o Linkedin utiliza essa busca, se tiver alguma maneira mais elegante e fácil de fazer essa implementação (ou plugin, porque procurei e não encontrei nada que fizesse no input, somente com input´s pré selecionados, o qual não foi aceito :( )

O que comentei acima foi isso que cheguei, mas não é uma validação correta e ainda não sei como ajustar.

Estou com dificuldade em 'juntar' as validações.

<code>/(?:^ *)?(?:\( *|())[A-Z](?: +(?:AND|OR) +[A-Z])?(?: *\)|)/</code>

Agradeço desde já a colaboração

3 respostas

Olá Ricardo,

o trabalho que você está tentando fazer não é possível usando só expressões regulares.

Vamos lá: o seu objetivo é dizer se uma string pertence a uma certa linguagem. Algo desse estilo:

São válidos:

  • (frase)

  • "frase"

  • frase AND frase

  • frase OR frase

  • NOT (frase)

  • palavra que só contém caracteres alfa-numéricos

Para isso é preciso de um analisador léxico, que divide uma frase em tokens e verifica se a frase pertence a linguagem que você especificou.

Implementar isso é relativamente fácil, basta ler um pouco sobre BNF (https://pt.wikipedia.org/wiki/Formalismo_de_Backus-Naur) e usar funções recursivas.

Dito isso, é possível que alguém já tenha implementado isso. Procure por um plugin :)

Então Victor, não sei se eu não soube me expressar ou se não entendi o que disse.

Acabei de ler o que sugeriu, muito obrigado. Desconhecia esse conteúdo que sugeriu, muito bom, mas acho que o REGEX (e talvez algo mais) resolva essa questão.

Uma busca booleana consiste de ambos os lados retornarem true or false.

Inicialmente penso em validar se os parenteses e as aspas estão devidamente fechadas.

Após isso, validar se a expressão por inteiro está correta e assim realizar a chamada backend.

(palavra AND palavra) OR palavra palavra AND palavra palavra AND "palavra composta" OR outra NOT texto

Basicamente isso, não penso ser algo muito complexo, mas realmente não estou sabendo montar as validações juntas.

Consegui validar as aspas e parênteses, mas não a sentença como um todo.

Olá Ricardo,

validar que todo parêntesis é fechado antes de abrir outro é fácil, mas nem é possível - com regex - validar que os parêntesis dentro de uma frase estão corretos, por exemplo em '((()(())()))'.

É possível fazer soft validations, no sentido que elas não garantem que a string é válida, mas sem elas com certeza não estaria.

Se quiser realmente garantir que todas suas buscas pertencem a esse tipo especifico de busca, recomendo o uso de um analisador léxico.

Abraços, Victor.