Hoe kan ik SQL-keywords markeren met behulp van een reguliere expressie?

stemmen
31

Ik wil graag SQL-keywords die binnen een string voorkomen in een syntax highlighter benadrukken. Hier zijn de regels die ik graag zou willen hebben:

  • Kom overeen met de trefwoorden SELECT en FROM (andere zullen worden toegevoegd, maar we beginnen hier). Moet all-caps zijn
  • Moet in een string zitten -- beginnend met 'of
  • Het eerste woord in die string (het negeren van spaties die eraan voorafgaan) zou een van de trefwoorden moeten zijn.

Dit is natuurlijk niet allesomvattend (kan ontsnappingen in een string negeren), maar ik wil hier graag beginnen.

Hier zijn een paar voorbeelden:

  • SELECT * FROM main -- zal niet overeenkomen (niet in een string)
  • SELECTEN NAAM VOOR HET HOOFDSTUK -- zal overeenkomen met

  • SELECTEN NAAM VOOR HET BELANGRIJK -- komt overeen met
  • Hier is een SQL-statement.

SELECTEN * VAN HET VOORZICHTIG -- nee, string begint niet met een trefwoord (SELECT...).

De enige manier waarop ik dacht het te doen in een enkele regex zou zijn met een negatieve blik achter de rug...maar dan zou het niet vaste breedte zijn, omdat we niet weten wanneer de string begint. Zoiets als:

Maar dit werkt natuurlijk niet:

enter

Zou zoiets mogelijk zijn in een enkele regex?

De vraag is gesteld op 25/05/2020 om 00:37
bron van user
In andere talen...                            


3 antwoorden

stemmen
0

Een geschikte reguliere expressie zal waarschijnlijk behoorlijk complex worden, vooral naarmate de regels verder evolueren. Zoals anderen hebben opgemerkt, kan het de moeite waard zijn om in plaats daarvan het gebruik van een parser te overwegen. Dit gezegd zijnde, is hier een mogelijke regex die probeert de tot nu toe genoemde regels te bedekken:

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

Regular expression visualization

Online demo's

  1. Debuggex Demo
  2. Regex101 Demo

Uitleg

Zoals te zien is in bovenstaande visualisatie, zoekt de regex aan het begin naar een dubbel of enkel citaat (opgeslagen in capturing group #1) en komt dan overeen met deze referentie aan het einde via \1. De SELECTen FROMtrefwoorden worden vastgelegd in capturing group #2 en #3. (De ?:(x|y)syntaxis zorgt ervoor dat er niet meer groepen zijn voor andere keuzes, aangezien ?:aan het begin van een keuze deze wordt uitgesloten als capturing group. ) Er zijn nog enkele andere optionele details zoals het beperken van wat is toegestaan tussen het SELECTen FROMen het niet tellen van het uiteindelijke aanhalingsteken als het onmiddellijk wordt opgevolgd door een woordkarakter.

Resultaten

id="pre-0"
antwoordde op 31/05/2020 om 13:55
bron van user

stemmen
0

Je zou het kunnen gebruiken om groepen vast te leggen:

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

In dit geval zou $2 verwijzen naar het eerste sleutelwoord en $3 naar het tweede sleutelwoord. Dit werkt ook alleen als er slechts twee trefwoorden zijn en slechts één string op een regel, wat waar lijkt te zijn in al uw voorbeelden, maar als die beperkingen niet werken voor u, laat het me weten.

antwoordde op 28/05/2020 om 19:39
bron van user

stemmen
0

Net getest de regexp bellow:

enter image description here

Als u andere commando's moet toevoegen kan het ding een klein trucje krijgen, omdat sommige trefwoorden niet van toepassing zijn. Bijvoorbeeld: ALTER TABLE mytable of UPDATE SET col = val;. Voor deze scenario's moet je subgroepen aanmaken en de regexp kan langzaam worden.

Met vriendelijke groet!

antwoordde op 28/05/2020 om 21:19
bron van user

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