Cum să evidențiați cuvintele cheie SQL folosind o expresie obișnuită?

voturi
31

Aș dori să evidențiez cuvintele cheie SQL care apar într-un șir într-un evidențiator de sintaxă. Iată regulile pe care aș dori să le am:

  • Potriviți cuvintele cheie SELECT și FROM (vor fi adăugate altele, dar vom începe aici). Trebuie să fie capace
  • Trebuie să fie conținut într-un șir - fie începând cu ' sau
  • Primul cuvânt din acest șir (ignorând spațiul alb precedent) ar trebui să fie unul dintre cuvintele cheie.

Desigur, acest lucru nu este cuprinzător (pot ignora scăpările dintr-un șir), dar aș dori să încep aici.

Iată câteva exemple:

  • SELECTA * DIN principal - nu se va potrivi (nu într-un șir)
  • SELECT nume din principal” - se va potrivi
  • "
    SELECTAȚI numele din principal "- se va potrivi
  • "" "Iată o declarație SQL:

SELECT * FROM principal "" "- nu, șirul nu începe cu un cuvânt cheie (SELECT ...).

Singurul mod în care m-am gândit să o fac într-o singură regex ar fi cu un aspect negativ în spatele ... dar atunci nu ar fi o lățime fixă, așa cum nu știm când începe șirul. Ceva asemănător cu:

Dar, desigur, nu va funcționa:

introduceți

S-ar putea face ceva ca acesta într-o singură regex?

Întrebat 25/05/2020 la 00:37
sursa de către utilizator
În alte limbi...                            


3 răspunsuri

voturi
0

O expresie regulată potrivită este probabil să devină destul de complexă, mai ales că regulile evoluează în continuare. După cum au remarcat alții, poate merita să vă luați în considerare utilizarea unui analizor. Acestea fiind spuse, iată o posibilă regex care încearcă să acopere regulile menționate până acum:

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

Vizualizare regulată a expresiilor

Demo-uri online

  1. Demo Debuggex
  2. Regex101 Demo

Explicaţie

După cum se poate observa în vizualizarea de mai sus, regex caută la început o ofertă dublă sau unică (salvată în capturarea grupului nr. 1) și apoi se potrivește cu această referință la sfârșit prin \1 . SELECT și FROM cuvintele cheie sunt capturate în grupurile de captare 2 și # 3. (The ?:(x|y) sintaxa asigură că nu există mai multe grupuri pentru alte opțiuni, cum ar fi ?: la începutul unei alegeri o exclude ca grup de captare.) Există alte detalii opționale, cum ar fi limitarea a ceea ce este permis între SELECT și FROM și fără a număra ghilimele finale dacă este succedat imediat de un personaj de cuvânt.

Rezultate

SELECT * FROM tbl        -- no match - not in a string
"SELECT * FROM tbl"      -- matches - in a double-quoted string
'SELECT * FROM tbl;'     -- matches - in a single-quoted string
'SELECT * FROM it's      -- no match - letter after end quote
"SELECT * FROM tbl'      -- no match - quotation marks don't match
'SELECT * FROM tbl"      -- no match - quotation marks don't match
"select * from tbl"      -- no match - keywords not upper case
'Select * From tbl'      -- no match - still not all upper case
"SELECT col1 FROM"       -- matches - even though no table name
'  SELECT  col1  FROM '  -- matches - as above with more whitespace
'SELECT col1, col2 FROM' -- matches - with multiple columns
Publicat 31/05/2020 la 13:55
sursa de către utilizator

voturi
0

Puteți utiliza grupuri de captare:

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

În acest caz, $ 2 s-ar referi la primul cuvânt cheie și 3 dolari s-ar referi la cel de-al doilea cuvânt cheie. Acest lucru funcționează numai dacă există doar două cuvinte cheie și un singur șir pe o linie, ceea ce pare a fi adevărat în toate exemplele dvs., dar dacă aceste restricții nu funcționează pentru dvs., anunțați-mă.

Publicat 28/05/2020 la 19:39
sursa de către utilizator

voturi
0

Tocmai am testat mai jos regexp:

introduceți descrierea imaginii aici

Dacă trebuie să adăugați alte comenzi, lucru poate primi un mic truc, deoarece unele cuvinte cheie nu se aplică. De exemplu: ALTER TABLA mytable sau UPDATE SET col = val ;. Pentru aceste scenarii va trebui să creați subgrupuri, iar regexp-ul poate deveni lent.

Toate cele bune!

Publicat 28/05/2020 la 21:19
sursa de către utilizator

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