Hvordan markere SQL-nøkkelord ved å bruke et vanlig uttrykk?

stemmer
31

Jeg vil fremheve SQL-nøkkelord som forekommer i en streng i en syntaksmarkør. Her er reglene jeg vil ha:

  • Samsvar med nøkkelordene VELG og FRA (andre vil bli lagt til, men vi starter her). Må være all-caps
  • Må være inneholdt i en streng - enten fra og med ' eller
  • Det første ordet i den strengen (når du ignorerer mellomrom foran den) skal være et av nøkkelordene.

Dette er selvfølgelig ikke omfattende (kan ignorere rømming i en streng), men jeg vil gjerne starte her.

Her er noen eksempler:

  • VELG * FRA hoved - stemmer ikke overens (ikke i en streng)
  • " VELG navn FRA hoved" - vil matche
  • "
    VELG navn fra hoved "- vil matche
  • "" "Her er en SQL-setning:

VELG * FRA hoved "" "- nei, streng starter ikke med et nøkkelord (VELG ...).

Den eneste måten jeg tenkte å gjøre det i en enkelt regex ville være med et negativt utseende ... men da ville det ikke være fast bredde, da vi ikke vet når strengen starter. Noe som:

Men dette fungerer selvfølgelig ikke:

legg

Ville noe slikt være mulig å gjøre i en enkelt regex?

Publisert på 25/05/2020 klokken 00:37
kilden bruker
På andre språk...                            


3 svar

stemmer
0

Et passende regelmessig uttrykk vil sannsynligvis bli ganske sammensatt, spesielt etter hvert som reglene utvikler seg ytterligere. Som andre har bemerket, kan det være verdt å vurdere å bruke en analyser i stedet. Når det er sagt, her er en mulig regex som forsøker å dekke reglene som er nevnt så langt:

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

Vanlig uttrykk visualisering

Online demonstrasjoner

  1. Debuggex-demo
  2. Regex101 Demo

Forklaring

Som det kan sees i visualiseringen ovenfor, ser regex etter enten et dobbelt- eller enkelt sitat i starten (lagret i fangstgruppe nr. 1) og samsvarer deretter med denne referansen på slutten via \1 . De SELECT og FROM nøkkelord blir fanget i gruppe # 2 og # 3. (De ?:(x|y) syntaks sørger for at det ikke er flere grupper for andre valg som ?: i starten av et valg ekskluderer det som en gruppe som fanger opp.) Det er noen ekstra valgfrie detaljer som å begrense hva som er tillatt mellom SELECT og FROM og ikke telle det endelige anførselstegnet hvis det umiddelbart blir etterfulgt av et ordtegn.

resultater

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
Svarte 31/05/2020 kl. 13:55
kilden bruker

stemmer
0

Du kan bruke fangstgrupper:

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

I dette tilfellet vil $ 2 referere til det første nøkkelordet og $ 3 referere til det andre søkeordet. Dette fungerer også bare hvis det bare er to nøkkelord og bare en streng på en linje, noe som ser ut til å være sant i alle eksemplene dine, men hvis disse begrensningene ikke fungerer for deg, gi meg beskjed.

Svarte 28/05/2020 kl. 19:39
kilden bruker

stemmer
0

Testet nettopp regexp-beltet:

legg inn bildebeskrivelse her

Hvis du trenger å legge til andre kommandoer, kan ting bli et lite triks, fordi noen nøkkelord ikke gjelder. F.eks: ALTER TABLE mytable eller UPDATE SET col = val ;. For disse scenariene må du opprette undergrupper, og regexp kan bli treg.

Med vennlig hilsen!

Svarte 28/05/2020 kl. 21:19
kilden bruker

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