Como destacar palavras-chave SQL usando uma expressão regular?

votos
32

Eu gostaria de destacar palavras-chave SQL que ocorrem dentro de uma string em um marcador de sintaxe. Aqui estão as regras que eu gostaria de ter:

  • Combine as palavras-chave SELECT e FROM (outras serão adicionadas, mas vamos começar aqui). Deve ser all-caps
  • Deve estar contido em uma string -- ou começando com 'ou
  • A primeira palavra nessa string (ignorando o espaço em branco que a precede) deve ser uma das palavras-chave.

Isto, claro, não é abrangente (pode ignorar fugas dentro de uma cadeia), mas gostaria de começar aqui.

Aqui estão alguns exemplos:

  • SELECT * FROM principal -- não vai corresponder (não em uma string)
  • SELECT name FROM main -- vai coincidir

  • SELECT name FROM main -- vai coincidir
  • Aqui está uma instrução SQL:

SELECT * FROM main -- não, string não começa com uma palavra-chave (SELECT...).

A única maneira que eu pensei em fazê-lo em um único regex seria com um olhar negativo... mas depois não seria largura fixa, pois não sabemos quando a corda começa. Algo do género:

Mas isto, claro, não vai funcionar:

enter

Seria possível fazer algo assim em um único regex?

Publicado 25/05/2020 em 00:37
fonte usuário
Em outras línguas...                            


3 respostas

votos
0

Uma expressão regular adequada é susceptível de se tornar bastante complexa, especialmente à medida que as regras evoluem mais. Como outros notaram, pode valer a pena considerar o uso de um interpretador. Dito isto, aqui está uma possível regex tentativa de cobrir as regras mencionadas até agora:

(["'])\s*(SELECT)(?:\s+|\s.*\s)(FROM)(?:\s+.*)?\1(?:[^\w]|$)

Regular expression visualization

Demonstrações Online

  1. Demonstração de Debuggex
  2. Regex101 Demonstração

Explicação

Como pode ser visto na visualização acima, o regex procura uma citação dupla ou única no início (gravada na captura do grupo # 1) e depois corresponde a esta referência no final via \1. As palavras-chave SELECTe FROMas palavras-chave são capturadas na captura dos grupos #2 e #3. (A ?:(x|y)sintaxe assegura que não há mais grupos para outras escolhas, pois ?:no início de uma escolha exclui-a como grupo de captura. ) Há alguns outros detalhes opcionais, como limitar o que é permitido entre a SELECTe FROMsem contar com a aspas final, se for imediatamente sucedido por um caractere de palavra.

Resultados

id="pré-0"
Respondeu 31/05/2020 em 13:55
fonte usuário

votos
0

Dava-lhe jeito capturar grupos:

(.*["']\s*\K)(?(1)(SELECT|FROM).*(SELECT|FROM)|)

Neste caso $2 referir-se-ia à primeira palavra-chave e $3 referir-se-ia à segunda palavra-chave. Isso também só funciona se houver apenas duas palavras-chave e apenas uma string em uma linha, o que parece ser verdade em todos os seus exemplos, mas se essas restrições não funcionarem para você, me avise.

Respondeu 28/05/2020 em 19:39
fonte usuário

votos
0

Basta testar a regexp abaixo:

enter image description here

Se você precisar adicionar outros comandos, a coisa pode ter um pequeno truque, porque algumas palavras-chave não se aplicam. Ex: ALTER TABLE mytable ou UPDATE SET col = val;. Para estes cenários você precisará criar subgrupos e a regexp pode se tornar lenta.

Com os melhores cumprimentos!

Respondeu 28/05/2020 em 21:19
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more