
 Θα ήθελα να επισημάνω τις λέξεις-κλειδιά SQL που εμφανίζονται σε μια συμβολοσειρά σε μια επισήμανση σύνταξης. Εδώ είναι οι κανόνες που θα ήθελα να έχω: 

* Ταιριάξτε τις λέξεις-κλειδιά SELECT και FROM (άλλες θα προστεθούν, αλλά θα ξεκινήσουμε εδώ). Πρέπει να είναι όλα τα καπάκια
* Πρέπει να περιέχεται σε μια συμβολοσειρά - είτε αρχίζει με `'` ή
* Η πρώτη λέξη σε αυτήν τη συμβολοσειρά (αγνοώντας το κενό διάστημα που προηγείται) πρέπει να είναι μία από τις λέξεις-κλειδιά.

 Αυτό φυσικά δεν είναι ολοκληρωμένο (μπορεί να αγνοήσει τις διαφυγές μέσα σε μια συμβολοσειρά), αλλά θα ήθελα να ξεκινήσω εδώ. 

 Ακολουθούν μερικά παραδείγματα: 

* SELECT * FROM main - δεν θα ταιριάζει (όχι σε συμβολοσειρά)
* " **SELECT** name **FROM** main" - θα ταιριάζει
* "   
 **SELECT** name **FROM** main "- θα ταιριάζει
* Ακολουθεί μια δήλωση SQL:

 SELECT * FROM main "" - Όχι, η συμβολοσειρά δεν ξεκινά με μια λέξη-κλειδί (SELECT ...). 

 Ο μόνος τρόπος που σκέφτηκα να το κάνω σε ένα μόνο regex θα ήταν με ένα αρνητικό βλέμμα πίσω ... αλλά τότε δεν θα ήταν σταθερό πλάτος, καθώς δεν γνωρίζουμε πότε ξεκινά η συμβολοσειρά. Κάτι όπως: 

* [`(?<=[']\s*(SELECT)\s*)(SELECT|FROM)`](https://regex101.com/r/AlfoxG/2)

 Αλλά αυτό φυσικά δεν θα λειτουργήσει: 

 [![εισάγετε](https://i.stack.imgur.com/rwPn5.png)](https://i.stack.imgur.com/rwPn5.png) 

 Μήπως κάτι τέτοιο θα ήταν δυνατό να γίνει σε ένα μόνο regex; 

 
Πώς να επισημάνετε τις λέξεις-κλειδιά SQL χρησιμοποιώντας μια κανονική έκφραση;
===============================================================================



 Μια κατάλληλη κανονική έκφραση είναι πιθανό να γίνει πολύ περίπλοκη, ειδικά καθώς οι κανόνες εξελίσσονται περαιτέρω. Όπως έχουν σημειώσει και άλλοι, ίσως αξίζει να εξετάσετε τη χρήση ενός προγράμματος ανάλυσης. Τούτου λεχθέντος, εδώ είναι ένα πιθανό regex που προσπαθεί να καλύψει τους κανόνες που αναφέρονται μέχρι στιγμής: 

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

![Οπτικοποίηση κανονικής έκφρασης](https://i.stack.imgur.com/XlYDs.png)

 Διαδικτυακές επιδείξεις
------------------------

1. [Επίδειξη Debuggex](https://www.debuggex.com/r/3sAaSxwOIo4nOcL0)
2. [Επίδειξη Regex101](https://regex101.com/r/zPMHMm/4)

 Εξήγηση
--------

 Όπως φαίνεται στην παραπάνω οπτικοποίηση, το regex αναζητά ένα διπλό ή ένα μόνο απόσπασμα στην αρχή (αποθηκεύεται στην ομάδα καταγραφής # 1) και στη συνέχεια ταιριάζει με αυτήν την αναφορά στο τέλος μέσω `\1` . ο `SELECT` και `FROM` οι λέξεις-κλειδιά καταγράφονται στις ομάδες καταγραφής # 2 και # 3. *(Ο `?:(x|y)` η σύνταξη διασφαλίζει ότι δεν υπάρχουν περισσότερες ομάδες για άλλες επιλογές όπως `?:` στην αρχή μιας επιλογής το αποκλείει ως ομάδα καταγραφής.)* Υπάρχουν μερικές επιπλέον προαιρετικές λεπτομέρειες, όπως ο περιορισμός των επιτρεπόμενων μεταξύ `SELECT` και `FROM` και δεν υπολογίζουμε το τελικό εισαγωγικό εάν το διαδέχεται αμέσως ένας χαρακτήρας λέξης. 

 Αποτελέσματα
-------------


```
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

```
 

 Θα μπορούσατε να χρησιμοποιήσετε ομάδες καταγραφής: 


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

```
 Σε αυτήν την περίπτωση, τα $ 2 θα αναφέρονται στην πρώτη λέξη-κλειδί και τα $ 3 θα αναφέρονται στη δεύτερη λέξη-κλειδί. Αυτό λειτουργεί επίσης μόνο εάν υπάρχουν μόνο δύο λέξεις-κλειδιά και μόνο μια συμβολοσειρά σε μια γραμμή, η οποία φαίνεται να ισχύει σε όλα τα παραδείγματα, αλλά εάν αυτοί οι περιορισμοί δεν λειτουργούν για εσάς, ενημερώστε με. 

 

 Μόλις δοκίμασα το regexp παρακάτω: 

 [![εισάγετε την περιγραφή της εικόνας εδώ](https://i.stack.imgur.com/Jg8Ke.png)](https://i.stack.imgur.com/Jg8Ke.png) 

 Εάν πρέπει να προσθέσετε άλλες εντολές, το πράγμα μπορεί να πάρει λίγο κόλπο, επειδή ορισμένες λέξεις-κλειδιά δεν ισχύουν. Π.χ .: ALTER TABLE mytable ή UPDATE SET col = val ;. Για αυτά τα σενάρια θα πρέπει να δημιουργήσετε υποομάδες και το regexp μπορεί να γίνει αργό. 

 Τις καλύτερες ευχές! 

 