Jak wyróżnić słowa kluczowe SQL za pomocą wyrażenia regularnego?

głosy
31

Chciałbym wyróżnić słowa kluczowe SQL, które występują wewnątrz łańcucha w kolorowaniu składni. Oto zasady, które chciałbym mieć:

  • Dopasowanie słów kluczowych SELECT i FROM (inne zostaną dodane, ale zaczniemy tutaj). Musi to być all-caps
  • Musi być zawarta w łańcuchu -- albo zaczynać się od 'albo
  • Pierwsze słowo w tym ciągu (ignorując poprzedzającą go białą przestrzeń) powinno być jednym ze słów kluczowych.

To oczywiście nie jest wyczerpujące (może zignorować ucieczki w ciągu), ale chciałbym zacząć od tego miejsca.

Oto kilka przykładów:

  • SELECT * FROM main -- nie pasuje (nie w łańcuchu)
  • SELECT name FROM main -- będzie pasować

  • SELECT name FROM main -- będzie pasować
  • Tu jest instrukcja SQL:

SELECT * FROM main -- nie, łańcuch nie zaczyna się od słowa kluczowego (SELECT...).

Jedyny sposób, w jaki myślałem, aby zrobić to w pojedynczym regeksie, byłby z negatywnym spojrzeniem w tył... ale wtedy nie byłaby to stała szerokość, ponieważ nie wiemy, kiedy łańcuch się zaczyna. Coś w tym stylu:

Ale to oczywiście nie zadziała:

enter

Czy coś takiego można by zrobić w jednym regeksie?

Utwórz 25/05/2020 o 00:37
źródło użytkownik
W innych językach...                            


3 odpowiedzi

głosy
0

Odpowiednie wyrażenie regularne może stać się dość skomplikowane, zwłaszcza w miarę dalszego rozwoju zasad. Jak zauważyli inni, może warto rozważyć użycie parsera. Mimo to, oto jeden z możliwych regexów, który próbuje objąć wspomniane dotąd reguły:

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

Regular expression visualization

Demaże online

  1. Debuggex Demo
  2. Regex101 Demo

Wyjaśnienie

Jak widać w powyższej wizualizacji, regex szuka albo podwójnego albo pojedynczego cytatu na początku (zapisanego w grupie przechwytywania #1), a następnie dopasowuje ten cytat na końcu poprzez \1. Hasła SELECTi FROMsłowa kluczowe są przechwytywane w uchwyconych grupach #2 i #3. (?:(x|y)Składnia zapewnia, że nie ma więcej grup do innych wyborów, ponieważ ?:na początku wyboru wyklucza go jako przechwytującą grupę. ) Istnieje kilka dalszych opcjonalnych szczegółów, takich jak ograniczenie tego, co jest dozwolone między znakiem cudzysłowu SELECTi FROMnie liczenie go, jeśli natychmiast zastąpi go znak słowny.

Wyniki

id="pre-0"
Odpowiedział 31/05/2020 o 13:55
źródło użytkownik

głosy
0

Przydadzą ci się grupy przechwytujące:

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

W tym przypadku $2 odnosiłoby się do pierwszego słowa kluczowego, a $3 do drugiego słowa kluczowego. To również działa tylko wtedy, gdy w jednym wierszu znajdują się tylko dwa słowa kluczowe i tylko jeden łańcuch, co wydaje się być prawdą we wszystkich twoich przykładach, ale jeśli te ograniczenia nie działają dla ciebie, daj mi znać.

Odpowiedział 28/05/2020 o 19:39
źródło użytkownik

głosy
0

Właśnie przetestowałem mieszek regexp:

enter image description here

Jeśli potrzebujesz dodać inne komendy, to może się okazać, że to trochę podstępne, ponieważ niektóre słowa kluczowe nie mają zastosowania. Eg: ALTER TABLE mytable or UPDATE SET col = val;. Dla tych scenariuszy będziesz musiał utworzyć podgrupy, a regexp może stać się powolny.

Pozdrawiam!

Odpowiedział 28/05/2020 o 21:19
źródło użytkownik

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