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

ψήφοι
31

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

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

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

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

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

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

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

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

εισάγετε

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

Δημοσιεύθηκε 25/05/2020 στις 00:37
πηγή χρήστη
Σε άλλες γλώσσες...                            


3 απαντήσεις

ψήφοι
0

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

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

Οπτικοποίηση κανονικής έκφρασης

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

  1. Επίδειξη Debuggex
  2. Επίδειξη Regex101

Εξήγηση

Όπως φαίνεται στην παραπάνω οπτικοποίηση, το 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
Απαντήθηκε 31/05/2020 στις 13:55
πηγή χρήστη

ψήφοι
0

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

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

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

Απαντήθηκε 28/05/2020 στις 19:39
πηγή χρήστη

ψήφοι
0

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

εισάγετε την περιγραφή της εικόνας εδώ

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

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

Απαντήθηκε 28/05/2020 στις 21:19
πηγή χρήστη

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