Διαδρομές
/
Factor
Factor
/
Ασκήσεις
/
Σκοπιά του καθολικού
Σκοπιά του καθολικού

Σκοπιά του καθολικού

Άσκηση εκμάθησης

Εισαγωγή

Γνωρίζεις ήδη τα βασικά: κλάσεις χαρακτήρων όπως \d και [A-Z], ποσοδείκτες όπως {4} και +, και τις λέξεις matches?, all-matching-subseqs και re-replace. Αυτή η άσκηση προσθέτει τα κομμάτια των κανονικών εκφράσεων που περιγράφουν δομή και συμφραζόμενα. Ζουν στο ίδιο λεξιλόγιο regexp, γραμμένα με το ίδιο literal R/ /.

Άγκυρες

Οι άγκυρες ταιριάζουν με μια θέση και όχι με έναν χαρακτήρα:

^    ! the start of the string
$    ! the end of the string
\b   ! a word boundary

Επειδή το $ σημαίνει το τέλος της συμβολοσειράς, γράψε \$ όταν εννοείς ένα κυριολεκτικό σύμβολο δολαρίου.

Ένα όριο λέξης (\b) είναι το σημείο όπου ένας χαρακτήρας λέξης συναντά έναν χαρακτήρα που δεν ανήκει σε λέξη. Οι χαρακτήρες λέξης είναι γράμματα, ψηφία και η κάτω παύλα· όλα τα υπόλοιπα (κενά, σημεία στίξης και τα δύο άκρα της συμβολοσειράς) μετράνε ως όριο. Έτσι, το \bcat\b ταιριάζει με το cat μόνο όταν στέκεται μόνο του:

USING: regexp ;

"cat nap" R/ \bcat\b/ re-contains? .   ! => t
"scatter" R/ \bcat\b/ re-contains? .   ! => f   (cat sits inside a word)

Ομαδοποίηση και εναλλαγή

Οι παρενθέσεις ( ) ομαδοποιούν ένα μέρος ενός μοτίβου, ώστε ένας ποσοδείκτης, ή ένα | ("αυτό ή εκείνο"), να εφαρμόζεται σε ολόκληρη την ομάδα:

USING: regexp ;

"abab" R/ (ab)+/ matches? .                ! => t   (+ applies to "ab")
"dog"  R/ cat|dog/ matches? .              ! => t   (either word)
"$100.50" R/ \$\d+(\.\d{2})?/ matches? .   ! => t
"$100"    R/ \$\d+(\.\d{2})?/ matches? .   ! => t   (the group is optional)

Το τελευταίο μοτίβο διαβάζεται ως εξής: "ένα σύμβολο δολαρίου, ένα ή περισσότερα ψηφία και μετά μια προαιρετική ομάδα από μια τελεία και δύο ψηφία".

Σημείωση: στη Factor μια ομάδα απλώς δομεί το μοτίβο. Σε αντίθεση με κάποια εργαλεία κανονικών εκφράσεων, δεν μπορείς να ανακτήσεις το κείμενο που ταίριαξε μια ομάδα: δεν υπάρχει εξαγωγή ομάδας σύλληψης και δεν υποστηρίζονται back-references όπως το \1. Για να ξεχωρίσεις κείμενο γύρω από ένα ορόσημο, χρησιμοποίησε lookaround (παρακάτω).

Lookaround: ταίριαξε με βάση τα συμφραζόμενα, χωρίς να τα καταναλώνεις

Ένα lookaround ελέγχει τι έρχεται ακριβώς πριν ή ακριβώς μετά το τρέχον σημείο χωρίς να κάνει αυτούς τους χαρακτήρες μέρος του ταιριάσματος. Είναι "μηδενικού πλάτους": αυτό που ελέγχει δεν συμπεριλαμβάνεται στο αποτέλεσμα.

(?=...)    ! lookahead:           ... must follow
(?!...)    ! negative lookahead:  ... must NOT follow
(?<=...)   ! lookbehind:          ... must come before
(?<!...)   ! negative lookbehind: ... must NOT come before

Το lookaround είναι επιλεκτικό: οι ίδιοι χαρακτήρες ταιριάζουν ή όχι ανάλογα με το τι βρίσκεται δίπλα τους. Ένα σκέτο \d+ αρπάζει κάθε αριθμό· το lookbehind και το lookahead κρατούν μόνο όσους έχουν τον σωστό γείτονα:

USING: regexp ;

"3 for $10 or 10 for $30" R/ \d+/ all-matching-subseqs .
! => { "3" "10" "10" "30" }   (every number)

"3 for $10 or 10 for $30" R/ (?<=\$)\d+/ all-matching-subseqs .
! => { "10" "30" }            (only the prices — the bare 3 and 10 drop)

"buy 2 at 15% off, 4 at 30% off" R/ \d+(?=%)/ all-matching-subseqs .
! => { "15" "30" }            (only the discounts — the bare 2 and 4 drop)

Επιλογές

Πρόσθεσε ένα γράμμα μετά το / κλεισίματος για να αλλάξεις τη συμπεριφορά ολόκληρου του μοτίβου. Το i το κάνει να αγνοεί τη διάκριση πεζών-κεφαλαίων:

USING: regexp ;

"REFUND"  R/ refund/i matches? .       ! => t
"Refund"  R/ refund/i matches? .       ! => t

Μετασχηματισμός κάθε ταιριάσματος

Το all-matching-subseqs σου δίνει το κείμενο που ταίριαξε. Το map-matches πάει ένα βήμα παραπέρα: εκτελεί ένα quotation σε κάθε ταίριασμα και συλλέγει τα αποτελέσματα. Το quotation λαμβάνει τη start θέση του ταιριάσματος, την end θέση του και ολόκληρη τη συμβολοσειρά· το subseq μετατρέπει αυτά τα τρία στο κείμενο που ταίριαξε, το οποίο μετά μετασχηματίζεις:

map-matches ( string regexp quot: ( start end string -- obj ) -- seq )
USING: math regexp sequences ;

"a1 b22 c333" R/ \d+/ [ subseq length ] map-matches .
! => { 1 2 3 }     (the length of each run of digits)

Ο ξάδελφός του που εκτελεί μόνο παρενέργειες, το each-match, εκτελεί ένα quotation σε κάθε ταίριασμα χωρίς να συλλέγει τίποτα.

Οδηγίες

Κρατάς τα βιβλία μιας μικρής εταιρείας και οι συναλλαγές της κάθε μέρας φτάνουν ως ακατάστατες γραμμές κειμένου. Θα χρησιμοποιήσεις κανονικές εκφράσεις για να επικυρώσεις ποσά, να βγάλεις νούμερα με βάση το σύμβολο που τα σημαδεύει και να επισημάνεις γραμμές που χρειάζονται πιο προσεκτική ματιά.

1. Επικύρωσε ένα ποσό

Ένα σωστά διαμορφωμένο ποσό αποτελείται από ένα $, ένα ή περισσότερα ψηφία και ένα προαιρετικό τμήμα λεπτών, δηλαδή μια τελεία ακολουθούμενη από ακριβώς δύο ψηφία: $100 ή $100.50, αλλά όχι $100.5. Όρισε τη valid-amount?, που επιστρέφει t όταν ολόκληρη η συμβολοσειρά είναι ένα σωστά διαμορφωμένο ποσό.

"$100.50" valid-amount? .   ! => t
"$100"    valid-amount? .   ! => t
"$100.5"  valid-amount? .   ! => f

2. Βγάλε τα ποσά σε δολάρια

Όρισε τη dollar-amounts, που επιστρέφει κάθε αριθμό που ακολουθεί αμέσως μετά από ένα $ στη γραμμή, μόνο τα ψηφία, χωρίς το $, με τη σειρά.

"spent $100 and $25 today" dollar-amounts .
! => { "100" "25" }

3. Βγάλε τα ποσοστά

Όρισε τη percentages, που επιστρέφει κάθε αριθμό που ακολουθείται αμέσως από ένα %.

"up 5% then down 12%" percentages .
! => { "5" "12" }

4. Επισήμανε μια γραμμή

Όρισε τη flagged?, που επιστρέφει t όταν η γραμμή αναφέρει refund ή chargeback με οποιονδήποτε συνδυασμό κεφαλαίων και πεζών γραμμάτων.

"Issued a REFUND today" flagged? .   ! => t
"a normal sale"         flagged? .   ! => f
Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα
Factor Exercism

Έτοιμος να ξεκινήσεις την άσκηση Σκοπιά του καθολικού;

Γράψου στο Exercism για να μάθεις και να κατακτήσεις Factor με 47 έννοιες163 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.