Οι κανονικές εκφράσεις (regex) είναι ένα ισχυρό εργαλείο για την εργασία με συμβολοσειρές στην Elixir. Οι κανονικές εκφράσεις στην Elixir ακολουθούν την προδιαγραφή PCRE (Perl Compatible Regular Expressions). Τα μοτίβα συμβολοσειρών που αντιπροσωπεύουν τη σημασία της κανονικής έκφρασης πρώτα μεταγλωττίζονται και στη συνέχεια χρησιμοποιούνται για το ταίριασμα όλης ή μέρους μιας συμβολοσειράς.
Στην Elixir, ο πιο συνηθισμένος τρόπος για να δημιουργήσεις κανονικές εκφράσεις είναι με το sigil ~r. Τα sigils παρέχουν συντακτική ζάχαρη, δηλαδή συντομεύσεις για συνηθισμένες εργασίες στην Elixir. Για να ταιριάξεις μια κυριολεκτική συμβολοσειρά, μπορείς να χρησιμοποιήσεις την ίδια τη συμβολοσειρά ως μοτίβο μετά το sigil.
~r/test/
Ο τελεστής =~/2 είναι χρήσιμος για να εκτελέσεις ένα ταίριασμα κανονικής έκφρασης σε μια συμβολοσειρά, το οποίο επιστρέφει ένα αποτέλεσμα boolean.
"this is a test" =~ ~r/test/
# => true
Δύο σημειώσεις για τη χρήση των sigils:
/
\)Το ταίριασμα ενός εύρους χαρακτήρων με αγκύλες [] ορίζει μια κλάση χαρακτήρων. Αυτή ταιριάζει έναν οποιονδήποτε χαρακτήρα με τους χαρακτήρες της κλάσης. Μπορείς επίσης να ορίσεις ένα εύρος χαρακτήρων όπως a-z, αρκεί η αρχή και το τέλος να αντιπροσωπεύουν ένα συνεχές εύρος σημείων κώδικα.
regex = ~r/[a-z][ADKZ][0-9][!?]/
"jZ5!" =~ regex
# => true
"jB5?" =~ regex
# => false
Οι συντομευμένες κλάσεις χαρακτήρων κάνουν το μοτίβο πιο συνοπτικό. Για παράδειγμα:
\d συντομογραφία του [0-9] (οποιοδήποτε ψηφίο)\w συντομογραφία του [A-Za-z0-9_] (οποιοσδήποτε χαρακτήρας "λέξης")\s συντομογραφία του [ \t\r\n\f] (οποιοσδήποτε χαρακτήρας κενού)Όταν μια συντομευμένη κλάση χαρακτήρων χρησιμοποιείται έξω από ένα sigil, πρέπει να γίνει escape: "\\d"
Οι εναλλαγές χρησιμοποιούν το | ως ειδικό χαρακτήρα για να δηλώσουν ότι ταιριάζει το ένα ή το άλλο
regex = ~r/cat|bat/
"bat" =~ regex
# => true
"cat" =~ regex
# => true
Οι ποσοδείκτες επιτρέπουν ένα επαναλαμβανόμενο μοτίβο στην κανονική έκφραση. Επηρεάζουν την ομάδα που προηγείται του ποσοδείκτη.
{N, M} όπου N είναι ο ελάχιστος αριθμός επαναλήψεων και M ο μέγιστος{N,} ταιριάζει N ή περισσότερες επαναλήψεις
{0,} μπορεί επίσης να γραφτεί ως *: ταιριάζει μηδέν ή περισσότερες επαναλήψεις{1,} μπορεί επίσης να γραφτεί ως +: ταιριάζει μία ή περισσότερες επαναλήψεις{,N} ταιριάζει μέχρι N επαναλήψειςΟι παρενθέσεις () χρησιμοποιούνται για να δηλώσουν ομάδες και συλλήψεις. Η ομάδα μπορεί επίσης να συλληφθεί σε ορισμένες περιπτώσεις ώστε να επιστραφεί για χρήση. Στην Elixir, αυτές μπορεί να είναι ονομασμένες ή ανώνυμες. Οι συλλήψεις ονομάζονται προσθέτοντας ?<name> μετά την παρένθεση ανοίγματος. Οι ομάδες λειτουργούν ως μία μονάδα, όπως όταν ακολουθούνται από ποσοδείκτες.
regex = ~r/(h)at/
Regex.replace(regex, "hat", "\\1op")
# => "hop"
regex = ~r/(?<letter_b>b)/
Regex.scan(regex, "blueberry", capture: :all_names)
# => [["b"], ["b"]]
Οι άγκυρες χρησιμοποιούνται για να δέσουν την κανονική έκφραση στην αρχή ή στο τέλος της συμβολοσειράς που πρόκειται να ταιριαστεί:
^ αγκυρώνει στην αρχή της συμβολοσειράς$ αγκυρώνει στο τέλος της συμβολοσειράςΕπειδή το ~r είναι μια συντόμευση για το "pattern" |> Regex.escape() |> Regex.compile!(), μπορείς επίσης να χρησιμοποιήσεις παρεμβολή συμβολοσειρών για να χτίσεις δυναμικά ένα μοτίβο κανονικής έκφρασης:
anchor = "$"
regex = ~r/end of the line#{anchor}/
"end of the line?" =~ regex
# => false
"end of the line" =~ regex
# => true
Σου έχει ανατεθεί να γράψεις μια υπηρεσία που δέχεται συμβάντα. Κάθε συμβάν έχει συνδεδεμένη μια ημερομηνία, αλλά παρατηρείς ότι τρεις διαφορετικές μορφές υποβάλλονται στο endpoint της υπηρεσίας σου:
"01/01/1970""January 1, 1970""Thursday, January 1, 1970"Βλέπεις ότι υπάρχουν κάποιες ομοιότητες μεταξύ τους και αποφασίζεις να γράψεις μερικά συνθέσιμα μοτίβα κανονικών εκφράσεων.
Υλοποίησε τις day/0, month/0 και year/0 ώστε να επιστρέφουν ένα μοτίβο συμβολοσειράς το οποίο, όταν μεταγλωττιστεί, θα αντιστοιχίζει τα αριθμητικά μέρη του "01/01/1970" (dd/mm/yyyy). Η ημέρα και ο μήνας μπορεί να εμφανίζονται ως 1 ή 01 (με μηδενικά στα αριστερά).
"31" =~ DateParser.day() |> Regex.compile!()
# => true
"12" =~ DateParser.month() |> Regex.compile!()
# => true
"1970" =~ DateParser.year() |> Regex.compile!()
# => true
Υλοποίησε τις day_names/0 και month_names/0 ώστε να επιστρέφουν ένα μοτίβο συμβολοσειράς το οποίο, όταν μεταγλωττιστεί, θα αντιστοιχίζει αντίστοιχα το όνομα της ημέρας της εβδομάδας και το όνομα του μήνα του έτους.
"Tuesday" =~ DateParser.day_names() |> Regex.compile!()
# => true
"June" =~ DateParser.month_names() |> Regex.compile!()
# => true
Υλοποίησε τις capture_day/0, capture_month/0, capture_year/0, capture_day_name/0, capture_month_name/0 ώστε να επιστρέφουν ένα μοτίβο συμβολοσειράς που συλλαμβάνει τα αντίστοιχα μέρη με τις ονομασίες: "day", "month", "year", "day_name", "month_name"
DateParser.capture_month_name()
|> Regex.compile!()
|> Regex.named_captures("December")
# => %{"month_name" => "December"}
Υλοποίησε τις capture_numeric_date/0, capture_month_name_date(), και capture_day_month_name_date/0 ώστε να επιστρέφουν ένα μοτίβο συμβολοσειράς που συλλαμβάνει τα μέρη από το μέρος 3 χρησιμοποιώντας την αντίστοιχη μορφή ημερομηνίας:
"01/01/1970"
"January 1, 1970"
"Thursday, January 1, 1970"
DateParser.capture_numeric_date()
|> Regex.compile!()
|> Regex.named_captures("01/01/1970")
# => %{"day" => "01", "month" => "01", "year" => "1970"}
Υλοποίησε τις match_numeric_date/0, match_month_name_date/0 και match_day_month_name_date/0 ώστε να επιστρέφουν μια μεταγλωττισμένη κανονική έκφραση που αντιστοιχίζει μόνο την ημερομηνία και μπορεί επίσης να συλλάβει τα μέρη.
"Thursday, January 1, 1970 was the Unix epoch." =~ DateParser.match_day_month_name_date()
# => false
"Thursday, January 1, 1970" =~ DateParser.match_day_month_name_date()
# => true
DateParser.match_day_month_name_date()
|> Regex.named_captures("Thursday, January 1, 1970")
# => %{
# "day" => "1",
# "day_name" => "Thursday",
# "month_name" => "January",
# "year" => "1970"
# }
Γράψου στο Exercism για να μάθεις και να κατακτήσεις Elixir με 58 έννοιες168 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.