Οι Κανονικές Εκφράσεις (Regular Expressions) στη Java είναι μια ισχυρή δυνατότητα που μας επιτρέπει να αναζητούμε και να αντικαθιστούμε συμβολοσειρές σε κείμενα, βάσει προκαθορισμένων προτύπων. Αυτά τα πρότυπα αποτελούνται από μια σειρά από χαρακτήρες και μετατρέπονται σε προγραμματιστικές εντολές που μπορούν να χρησιμοποιηθούν για την αναζήτηση και την επεξεργασία των κειμένων.
Για παράδειγμα, μπορούμε να χρησιμοποιήσουμε τις Κανονικές Εκφράσεις για να αναζητήσουμε όλες τις λέξεις που αρχίζουν με το γράμμα “c” σε ένα κείμενο. Η σύνταξη της Κανονικής Εκφράσης στην Java είναι η εξής:
String regex = "^c.*";
Η παραπάνω Κανονική Έκφραση εξηγείται ως εξής:
- “^” συμβολίζει ότι η λέξη θα πρέπει να αρχίζει με το γράμμα “c”.
- “.” συμβολίζει όποιον χαρακτήρα και να είναι.
- “*” συμβολίζει ότι οποιοσδήποτε χαρακτήρας, συμπεριλαμβανομένου του κενού, μπορεί να ακολουθήσει το “c”.
Με τη χρήση της Κανονικής Εκφρασης που ορίζει αυτό το πρότυπο, μπορούμε να ελέγξουμε αν μια συμβολοσειρά αρχίζει με το γράμμα “c” και να επιστρέψουμε μια λίστα με όλες τις λέξεις που ταιριάζουν στο πρότυπο.
Μια απλή εφαρμογή των Κανονικών Εκφράσεων στη Java είναι η εύρεση της συχνότητας εμφάνισης ενός συγκεκριμένου όρου σε ένα κείμενο. Για παράδειγμα, αν θέλουμε να βρούμε πόσες φορές εμφανίζεται η λέξη “Java” σε ένα κείμενο, μπορούμε να χρησιμοποιήσουμε την ακόλουθη Κανονική Έκφραση:
String regex = "\\bJava\\b";
Η Κανονική Έκφραση που ορίζει αυτό το πρότυπο σημαίνει:
- “\b” συμβολίζει ότι η λέξη θα πρέπει να είναι σε ξεχωριστή λέξη (όχι μέρος μιας άλλης λέξης).
- “Java” συμβολίζει τη λέξη που αναζητούμε.
Με τη χρήση της Κανονικής Έκφρασης αυτής, μπορούμε να επιστρέψουμε τον αριθμό των φορών που εμφανίζεται η λέξη “Java” στο κείμενο.
[adinserter block=”2″]
Συνολικά, οι Κανονικές Εκφράσεις είναι ένα πολύ χρήσιμο εργαλείο για την επεξεργασία συμβολοσειρών στη Java και μπορούν να χρησιμοποιηθούν σε μια πληθώρα καταστάσεων. Ορισμένες από τις χρήσεις των Κανονικών Εκφράσεων στη Java είναι οι εξής:
- Αναζήτηση συμβολοσειρών που πληρούν ένα πρότυπο.
- Αντικατάσταση τμημάτων συμβολοσειρών που πληρούν ένα πρότυπο.
- Επιστροφή τμημάτων συμβολοσειρών που πληρούν ένα πρότυπο.
- Έλεγχος της συντακτικής ορθότητας μιας συμβολοσειράς.
- Εξαγωγή δεδομένων από μια συμβολοσειρά με βάση ένα πρότυπο.
- Αναδιάταξη συμβολοσειρών σε ένα συγκεκριμένο μοτίβο.
Η Java παρέχει την κλάση java.util.regex για τη χρήση Κανονικών Εκφράσεων στην προγραμματιστική της πλατφόρμα. Η κλάση αυτή περιέχει μια σειρά από μεθόδους για τη διεκπεραίωση ερωτημάτων με βάση μια Κανονική Έκφραση, όπως η compile() για τη δημιουργία ενός αντικειμένου Pattern που αντιστοιχεί στην Κανονική Έκφραση, και η matcher() για τη δημιουργία ενός αντικειμένου Matcher που χρησιμοποιείται για την εφαρμογή της Κανονικής Έκφρασης σε μια συμβολοσειρά.
Παρακάτω δίνεται ένα παράδειγμα κώδικα στην Java για την αναζήτηση λέξεων που αρχίζουν με το γράμμα “c” σε ένα κείμενο:
import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexExample { public static void main(String[] args) { String text = "Cats are cute, but cockroaches are creepy."; String regex = "^c.*"; Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(text); while(matcher.find()) { System.out.println("Match found at index "+ matcher.start() +" - "+ matcher.group()); } } }
Στο παραπάνω παράδειγμα, η Κανονική Έκφραση “^c.*” χρησιμοποιείται για να βρεθούν όλες οι λέξεις που αρχίζουν με το γράμμα “c” στη συμβολοσειρά “Cats are cute, but cockroaches are creepy.” Η compile() μέθοδος δημιουργεί ένα αντικείμενο Pattern που αντιστοιχεί στην Κανονική Έκφραση και η matcher() μέθοδος δημιουργεί ένα αντικείμενο Matcher που χρησιμοποιείται για την εφαρμογή της Κανονικής Έκφρασης στο κείμενο. Τέλος, η while() επαναλαμβάνει την αναζήτηση για όλες τις λέξεις που ταιριάζουν στο πρότυπο και εκτυπώνει το αποτέλεσμα στην οθόνη.
Ένα απλό λάθος που μπορεί να προκύψει κατά τη χρήση Κανονικών Εκφράσεων στη Java είναι η λανθασμένη διαχείριση ειδικών χαρακτήρων, όπως οι αναδρομικοί χαρακτήρες. Για παράδειγμα, αν χρησιμοποιηθεί η Κανονική Έκφραση “\d+” για την αναζήτηση αριθμητικών τιμών σε ένα κείμενο, αυτή θα επιστρέψει όλους τους συνεχόμενους αριθμούς στο κείμενο. Αν όμως η Κανονική Έκφραση “\d{3}” χρησιμοποιηθεί για την αναζήτηση ακριβώς τριών ψηφίων, η έκφραση αυτή θα επιστρέψει μόνο τους αριθμούς που αποτελούνται ακριβώς από τρία ψηφία.
[adinserter block=”3″]
Συνολικά, η χρήση Κανονικών Εκφράσεων στη Java μπορεί να είναι πολύ χρήσιμη κατά τη διαχείριση συμβολοσειρών, επιτρέποντας στους προγραμματιστές να εκφράζουν πρότυπα και να εκτελούν πράξεις πάνω σε συμβολοσειρές με απλό και ευανάγνωστο τρόπο.
Οι σημαίες (flags) που μπορούν να χρησιμοποιηθούν στην compile() μέθοδο αλλάζουν τον τρόπο με τον οποίο γίνεται η αναζήτηση. Ορισμένες από αυτές είναι οι εξής:
- Pattern.CASE_INSENSITIVE: Τα πεζά και τα κεφαλαία γράμματα θα αγνοηθούν κατά την αναζήτηση.
- Pattern.LITERAL: Ειδικοί χαρακτήρες στο πρότυπο θα θεωρηθούν ως συνηθισμένοι χαρακτήρες κατά την αναζήτηση.
- Pattern.UNICODE_CASE: Χρησιμοποιείται μαζί με την σημαία CASE_INSENSITIVE για να αγνοηθούν τα κεφαλαία και τα πεζά γράμματα που βρίσκονται εκτός του αγγλικού αλφαβήτου.
Μπορούν επίσης να χρησιμοποιηθούν και άλλες σημαίες, όπως η DOTALL που καθιστά τον χαρακτήρα ‘.’ να ταιριάζει σε οποιοδήποτε χαρακτήρα, συμπεριλαμβανομένων των χαρακτήρων νέας γραμμής. Μπορούν επίσης να συνδυαστούν διάφορες σημαίες για να πετύχουμε το επιθυμητό αποτέλεσμα. Για παράδειγμα, η συνδυασμένη χρήση των CASE_INSENSITIVE και UNICODE_CASE σημαιών θα κάνει την αναζήτηση να αγνοεί τα πεζά και κεφαλαία γράμματα που βρίσκονται
Μπορούμε να χρησιμοποιήσουμε επίσης τη σημαία MULTILINE για να υποστηρίξουμε την αναζήτηση σε πολλαπλές γραμμές στο κείμενο. Αν η σημαία αυτή δεν χρησιμοποιηθεί, οι ειδικοί χαρακτήρες ‘^’ και ‘$’ αντιστοιχούν μόνο στην αρχή και το τέλος της συμβολοσειράς αντίστοιχα. Αν η σημαία αυτή χρησιμοποιηθεί, οι ειδικοί χαρακτήρες ‘^’ και ‘$’ αντιστοιχούν στην αρχή και το τέλος κάθε γραμμής αντίστοιχα.
Ένα απλό λάθος που μπορεί να προκύψει κατά τη χρήση σημαίων στην Java είναι η ανάθεση λανθασμένης σημαίας στο αντικείμενο Pattern. Για παράδειγμα, αν η σημαία UNICODE_CASE χρησιμοποιηθεί χωρίς τη σημαία CASE_INSENSITIVE, η αναζήτηση δεν θα αγνοεί τα κεφαλαία και πεζά γράμματα που βρίσκονται εκτός του αγγλικού αλφαβήτου.
Συνολικά, η χρήση σημαίων στη Java μπορεί να βοηθήσει στην προσαρμογή της αναζήτησης στις ανάγκες του προγράμματος και να βελτιώσει την αποτελεσματικότητα της αναζήτησης σε συμβολοσειρές.
Το πρώτο όρισμα της μεθόδου Pattern.compile() είναι το πρότυπο (pattern). Αυτό περιγράφει τι αναζητείται.
Τα αγκίστρα χρησιμοποιούνται για την αναζήτηση μιας σειράς χαρακτήρων:
Έκφραση | Περιγραφή |
---|---|
[abc] | Βρίσκει έναν χαρακτήρα από τις επιλογές μέσα στα αγκίστρα |
[^abc] | Βρίσκει έναν χαρακτήρα που ΔΕΝ βρίσκεται ανάμεσα στα αγκίστρα |
Μπορούν επίσης να χρησιμοποιηθούν και άλλοι ειδικοί χαρακτήρες και σύμβολα για την αναζήτηση σε περισσότερα από ένα χαρακτήρες, όπως η χρήση του χαρακτήρα “.” που αντιπροσωπεύει έναν οποιονδήποτε χαρακτήρα, ή η χρήση του χαρακτήρα “*” που αντιπροσωπεύει μηδέν ή περισσότερους από τον προηγούμενο χαρακτήρα.
Για παράδειγμα, το πρότυπο “a.c” θα βρει οποιαδήποτε συμβολοσειρά η οποία έχει ένα “a” στην αρχή, ένα οποιοδήποτε χαρακτήρα στη μέση, και ένα “c” στο τέλος. Επίσης, το πρότυπο “ab*” θα βρει οποιαδήποτε συμβολοσειρά που ξεκινά με “a” και στη συνέχεια έχει μηδέν ή περισσότερους “b” χαρακτήρες.
Επιπλέον, μπορούν να χρησιμοποιηθούν ειδικές ακολουθίες χαρακτήρων για την αναζήτηση πολύ συγκεκριμένων πραγμάτων, όπως οι ακολουθίες “\d” που αντιπροσωπεύει έναν ψηφίο, ή η ακολουθία “\s” που αντιπροσωπεύει χαρακτήρες κενού χώρου όπως τα κενά ή οι χαρακτήρες νέας γραμμής. Μπορούν επίσης να χρησιμοποιηθούν ακολουθίες όπως το “\b” που αντιπροσωπεύει την αρχή ή το τέλος ενός λέξης.
Μια συνηθισμένη πηγή σφαλμάτων με τις regular expressions είναι η μη σωστή χρήση των ειδικών χαρακτήρων. Για παράδειγμα, η χρήση του χαρακτήρα “\” για την αποφυγή της ειδικής σημασίας ενός χαρακτήρα, πρέπει να προστατεύεται διπλός, π.χ. “\”. Αν ο χαρακτήρας “\” δεν προστατευθεί κατάλληλα, μπορεί να οδηγήσει σε συντακτικά λάθη και σφάλματα.
Συνολικά, οι regular expressions είναι ένα ισχυρό εργαλείο για την
αναζήτηση και τον προσδιορισμό συμβολοσειρών σε μια ποικιλία σεναρίων στην Java. Η σωστή χρήση των συντακτικών τους και η κατανόηση των ειδικών χαρακτήρων και των σημαιών είναι ζωτικής σημασίας για την επίτευξη αποτελεσματικών και ακριβών αναζητήσεων.
[adinserter block=”4″]
Είναι σημαντικό να θυμάστε ότι η απόδοση των regular expressions μπορεί να επηρεαστεί σοβαρά από τη σύνθεση και το μέγεθος της συμβολοσειράς που αναζητείται, καθώς και από την πολυπλοκότητα του προτύπου που χρησιμοποιείται. Για παράδειγμα, η αναζήτηση ενός πολύπλοκου προτύπου σε ένα μεγάλο αρχείο μπορεί να είναι πολύ αργή και να οδηγήσει σε καταστροφική καθυστέρηση. Για αυτό το λόγο, είναι σημαντικό να εξετάζονται τα περιβάλλοντα και οι προδιαγραφές της εφαρμογής πριν από τη χρήση regular expressions και να γίνεται βελτιστοποίηση της κώδικας όπου είναι απαραίτητο.
Οι Metacharacters είναι χαρακτήρες με ειδική σημασία στις regular expressions. Οι συνηθέστεροι Metacharacters στην Java είναι οι εξής:
Χαρακτήρας | Σημασία |
---|---|
. | Οποιοσδήποτε χαρακτήρας, εκτός από τον χαρακτήρα νέας γραμμής |
\d | Βρείτε έναν ψηφίο |
\D | Βρείτε έναν χαρακτήρα, που δεν είναι ψηφίο |
\s | Βρείτε χαρακτήρες κενού χώρου |
\S | Βρείτε χαρακτήρες που δεν είναι κενός χώρος |
\w | Βρείτε χαρακτήρες λέξης (αλφαριθμητικοί χαρακτήρες) |
\W | Βρείτε χαρακτήρες που δεν είναι χαρακτήρες λέξης |
\b | Βρείτε την αρχή ή το τέλος μιας λέξης |
\B | Βρείτε ένα σημείο που δεν είναι αρχή ή τέλος μιας λέξης |
^ | Βρείτε την αρχή μιας συμβολοσειράς |
$ | Βρείτε το τέλος μιας συμβολοσειράς |
[] | Ορίζουν ένα εύρος χαρακτήρων |
[^] | Όλοι οι χαρακτήρες πλην των προσδιορισμένων |
Μπορείτε να χρησιμοποιήσετε αυτούς τους χαρακτήρες σε συνδυασμό με άλλους χ
Οι Metacharacters χρησιμοποιούνται για την εύρεση συγκεκριμένων χαρακτήρων και συμβολοσειρών μέσω της διαδικασίας των regular expressions. Για παράδειγμα, ο χαρακτήρας “.” μπορεί να χρησιμοποιηθεί για την αναζήτηση οποιουδήποτε χαρακτήρα εκτός από τον χαρακτήρα νέας γραμμής σε μια συμβολοσειρά. Επίσης, ο χαρακτήρας “\d” μπορεί να χρησιμοποιηθεί για την αναζήτηση ψηφίων και ο χαρακτήρας “\s” μπορεί να χρησιμοποιηθεί για την αναζήτηση χαρακτήρων κενού χώρου.
Επιπλέον, οι αγκύλες “[]” μπορούν να χρησιμοποιηθούν για να ορίσουν ένα εύρος χαρακτήρων. Για παράδειγμα, οι χαρακτήρες “[abc]” θα βρουν οποιονδήποτε από τους χαρακτήρες “a”, “b” ή “c”, ενώ οι χαρακτήρες “[0-9]” θα βρουν οποιονδήποτε από τους ψηφίους από 0 έως 9.
Επιπλέον, ο χαρακτήρας “^” χρησιμοποιείται για να βρει την αρχή μιας συμβολοσειράς, ενώ ο χαρακτήρας “$” χρησιμοποιείται για να βρει το τέλος μιας συμβολοσειράς. Ο χαρακτήρας “\b” χρησιμοποιείται για να βρει την αρχή ή το τέλος μιας λέξης.
Είναι σημαντικό να θυμάστε ότι ορισμένοι Metacharacters, όπως ο χαρακτήρας “.” και ο χαρακτήρας “[“, είναι επίσης ειδικοί χαρακτήρα και πρέπει να διπλασιαστούν όταν χρησιμοποιούνται ως απλοί χαρακτήρες στην αναζήτηση. Για παράδειγμα, αν θέλετε να βρείτε έναν χαρακτήρα “[” σε μια συμβολοσειρά, πρέπει να γράψετε τον χαρακτήρα αυτόν τρεις φορές, δηλαδή “[[[“.
Επίσης, μπορείτε να συνδυάσετε Metacharacters για πιο σύνθετες αναζητήσεις. Για παράδειγμα, οι χαρακτήρες “\b\w+\b” θα βρουν οποιαδήποτε λέξη σε μια συμβολοσειρά.
[adinserter block=”5″]
Τέλος, ο χαρακτήρας “\” χρησιμοποιείται για τη διαφυγή (escape) των Metacharacters, ώστε να αναζητήσετε τον χαρακτήρα αυτόν αντί για τη σημασία του ως Metacharacter. Για παράδειγμα, αν θέλετε να βρείτε τον χαρακτήρα “.”, πρέπει να χρησιμοποιήσετε τη σύνταξη “.”.
Συνολικά, η χρήση των Metacharacters είναι ένας ισχυρός τρόπος αναζήτησης συμβολοσειρών στην Java και μπορεί να βοηθήσει στην επίτευξη ακριβών και αποτελεσματικών αναζητήσεων.
Οι Quantifiers καθορίζουν τις ποσότητες των επαναλήψεων στο πλαίσιο των ρυθμίσεων αναζήτησης. Εδώ είναι μερικά παραδείγματα Quantifiers:
Quantifier | Περιγραφή |
---|---|
n+ | Αντιστοιχεί σε οποιαδήποτε συμβολοσειρά που περιέχει τουλάχιστον ένα n |
n* | Αντιστοιχεί σε οποιαδήποτε συμβολοσειρά που περιέχει μηδενικές ή περισσότερες εμφανίσεις του n |
n? | Αντιστοιχεί σε οποιαδήποτε συμβολοσειρά που περιέχει μηδενικές ή μία εμφάνιση του n |
n{x} | Αντιστοιχεί σε οποιαδήποτε συμβολοσειρά που περιλαμβάνει μια ακολουθία X n |
n{x,y} | Αντιστοιχεί σε οποιαδήποτε συμβολοσειρά που περιλαμβάνει μια ακολουθία από X έως Y εμφανίσεις του n |
n{x,} | Αντιστοιχεί σε οποιαδήποτε συμβολοσειρά που περιλαμβάνει μια ακολουθία από τουλάχιστον X εμφανίσεις του n |
Συνεχίζοντας, υπάρχουν και άλλα Quantifiers που μπορείτε να χρησιμοποιήσετε στα πρότυπά σας:
Quantifier | Περιγραφή |
---|---|
n{0,1} | Αντιστοιχεί σε οποιαδήποτε συμβολοσειρά που περιλαμβάνει μηδενικές ή μία εμφάνιση του n |
n{0,} | Αντιστοιχεί σε οποιαδήποτε συμβολοσειρά που περιλαμβάνει μηδενικές ή περισσότερες εμφανίσεις του n |
n{1,} | Αντιστοιχεί σε οποιαδήποτε συμβολοσειρά που περιλαμβάνει τουλάχιστον μία εμφάνιση του n |
n{X} | Αντιστοιχεί σε οποιαδήποτε συμβολοσειρά που περιλαμβάνει ακριβώς X εμφανίσεις του n |
n+? | Αντιστοιχεί σε οποιαδήποτε συμβολοσειρά που περιέχει τουλάχιστον μία εμφάνιση του n, σε ακριβή αντιστοίχιση |
n*? | Αντιστοιχεί σε οποιαδήποτε συμβολοσειρά που περιέχει μηδενικές ή περισσότερες εμφανίσεις του n, σε ακριβή αντιστοίχιση |
n?? | Αντιστοιχεί σε οποιαδήποτε συμβολοσειρά που περιέχει μηδενικές ή μία εμφάνιση του n, σε ακριβή αντιστοίχιση |
Συνεχίζοντας, ορισμένα ακόμη Quantifiers που μπορείτε να χρησιμοποιήσετε είναι:
Quantifier | Περιγραφή |
---|---|
n{X,Y}? | Αντιστοιχεί σε οποιαδήποτε συμβολοσειρά που περιλαμβάνει μια ακολουθία από τουλάχιστον X εμφανίσεις του n, αλλά όχι περισσότερες από Y εμφανίσεις, σε ακριβή αντιστοίχιση |
n$ | Αντιστοιχεί σε οποιαδήποτε συμβολοσειρά που τελειώνει με τον χαρακτήρα n |
^n | Αντιστοιχεί σε οποιαδήποτε συμβολοσειρά που αρχίζει με τον χαρακτήρα n |
?=n | Αντιστοιχεί σε οποιαδήποτε συμβολοσειρά που ακολουθείται από τον χαρακτήρα n |
?!n | Αντιστοιχεί σε οποιαδήποτε συμβολοσειρά που ΔΕΝ ακολουθείται από τον χαρακτήρα n |
Σημείωση: Η χρήση των Quantifiers είναι σημαντική στην αναζήτηση συμβολοσειρών και στη διαχείριση των δεδομένων.