Τελεστές εύρους και flip-flop#
Δύο τελεστές με δύο εντελώς διαφορετικές εργασίες ανάλογα με το περιβάλλον: σε περιβάλλον λίστας δημιουργούν εύρη, και σε βαθμωτό περιβάλλον είναι εκφράσεις λογικής τιμής με κατάσταση τύπου «flip-flop» για αντιστοίχιση εύρους γραμμών σε επεξεργασία ροής.
Τελεστής | Εργασία σε περιβάλλον λίστας | Εργασία σε βαθμωτό περιβάλλον |
|---|---|---|
| περιεκτικό εύρος | flip-flop (ελεγμένη-ψευδής εισαγωγή) |
| περιεκτικό εύρος | flip-flop (ελεγμένη-αληθής εισαγωγή) |
.. σε περιβάλλον λίστας - εύρη#
Σε περιβάλλον λίστας, ο .. παράγει την περιεκτική ακολουθία μεταξύ των ακραίων σημείων:
0..9 # (0,1,2,3,4,5,6,7,8,9)
'a'..'z' # ('a','b',...,'y','z') 26 elements
'aa'..'zz' # ('aa','ab',...,'zy','zz') 676 elements
'A'..'F' # ('A','B','C','D','E','F')
for my $i (1..100) { ... } # numeric for-loop
for my $name ('alpha'..'omega') { ... } # alphabetic, magic-incremented
Για αριθμητικά ακραία σημεία το αποτέλεσμα είναι η ακέραια ακολουθία (με αυστηρή σειρά - η 5..1 είναι κενή λίστα, ποτέ αντεστραμμένη). Για ακραία σημεία συμβολοσειρών χρησιμοποιείται η μαγική αύξηση από ++, που σας δίνει τη φυσική αλφαβητική εξάπλωση (και από 'aa' μέχρι 'zz' τους αναμενόμενους 676 δυόψηφους συνδυασμούς).
Ένα κοινό ιδίωμα Perl:
my @hex = ('0'..'9', 'a'..'f'); # 16 hex digits as strings
my @rev = reverse 1..10; # (10,9,8,...,1)
@arr[ 5..9 ] # array slice, indexes 5..9
@arr[ -3..-1 ] # last three elements
Το εξ ολοκλήρου ακέραιο εύρος μπορεί να είναι πολύ μεγάλο - η 1..1_000_000_000 είναι λίστα ενός δισεκατομμυρίου στοιχείων. Η Perl 5 δημιουργεί νωχελικά τα εύρη βρόχου στη for, οπότε η for my $i (1..1_000_000_000) είναι ασφαλής, αλλά η my @x = 1..1_000_000_000 δεσμεύει ολόκληρο τον πίνακα. Η PetaPerl ακολουθεί τον ίδιο κανόνα.
Αντεστραμμένα ακραία σημεία#
Η 5..1 είναι κενή. Δεν υπάρχει μορφή «αντεστραμμένου εύρους»· αν θέλετε φθίνουσα σειρά, δημιουργήστε αύξουσα και κάντε reverse:
1..5 # (1,2,3,4,5)
5..1 # () - empty, no warning
reverse 1..5 # (5,4,3,2,1)
Ακραία σημεία μικτού τύπου#
Αν κάποιο ακραίο σημείο μοιάζει αριθμητικό, ο .. κάνει αριθμητικό εύρος:
'1'..'5' # (1,2,3,4,5) - numeric
'1'..'10' # (1,2,3,4,5,6,7,8,9,10) - numeric
'a'..'5' # ('a') - magic-increment from "a",
# stops because it can't reach "5"
Κάντε τον τύπο ρητό για αποφυγή σύγχυσης:
0+'1' .. 0+'5' # numeric, no doubt
sprintf("%d", 1) .. sprintf("%d", 5)
Στην πράξη, γράψτε ακέραια εύρη με σκέτα κυριολεκτικά ακεραίων και εύρη χαρακτήρων με σκέτα γράμματα σε εισαγωγικά· η διάκριση μαγικής-έναντι-αριθμητικής ακολουθεί αυτόματα.
.. και ... σε βαθμωτό περιβάλλον - flip-flops#
Μέσα σε λογικό περιβάλλον (ένα if, ένα while, ένα ?:, τα δεξιά ενός &&/||///), ο .. γίνεται μια έκφραση με κατάσταση που θυμάται αν βρίσκεται αυτή τη στιγμή μεταξύ αντιστοιχίας αριστερής πλευράς και αντιστοιχίας δεξιάς πλευράς.
while (<$fh>) {
if (/^BEGIN/ .. /^END/) { # true from BEGIN line through END line
print; # print everything in between, inclusive
}
}
Η σημασιολογία:
Το flip-flop είναι αρχικά ψευδές.
Όταν η αριστερή συνθήκη (
/^BEGIN/) γίνει αληθής, το flip-flop μεταβαίνει σε αληθές, και η δεξιά πλευρά αποτιμάται αμέσως στην ίδια επανάληψη.Το flip-flop παραμένει αληθές στις επόμενες επαναλήψεις μέχρι η δεξιά συνθήκη (
/^END/) να γίνει αληθής. Σε εκείνη την επανάληψη επιστρέφει αληθές και στη συνέχεια μεταβαίνει πάλι σε ψευδές.Έτσι τόσο η γραμμή BEGIN όσο και η γραμμή END συμπεριλαμβάνονται.
Όταν το flip-flop είναι αληθές, επιστρέφει έναν αύξοντα αριθμό (1 στην επανάληψη εισόδου, 2 στην επόμενη, …). Στην κλείνουσα επανάληψη επιστρέφει το πλήθος ακολουθούμενο από E0 - οπότε η τιμή είναι αληθής (μη κενή συμβολοσειρά, όχι το ψευδές "0") αλλά μετατρέπεται σε συμβολοσειρά ως ο αριθμός 0 για κοσμητική σαφήνεια. Συνήθως μπορείτε να το αντιμετωπίσετε ως απλή λογική τιμή.
Ο ... διαφέρει από τον .. σε μία λεπτομέρεια:
..(δύο τελείες) - όταν η αριστερή πλευρά γίνει αληθής, η δεξιά πλευρά ελέγχεται στην ίδια επανάληψη. Έτσι η ίδια γραμμή μπορεί να ανοίξει και να κλείσει το εύρος....(τρεις τελείες) - όταν η αριστερή πλευρά γίνει αληθής, η δεξιά πλευρά δεν ελέγχεται μέχρι την επόμενη επανάληψη. Πάντα εύρος πολλαπλών γραμμών.
while (<$fh>) {
print if /<head>/ .. /<\/head>/; # one-line <head>...</head> works
print if /<head>/ ... /<\/head>/; # forces multi-line; same-line ignored
}
Πότε θα χρησιμοποιούσατε flip-flop#
Το flip-flop λάμπει στο φιλτράρισμα εύρους γραμμών τύπου awk - εξαγωγή τμημάτων από αρχείο καταγραφής, απομόνωση περιφραγμένου μπλοκ κώδικα από markdown, επεξεργασία μπλοκ ρυθμίσεων οριοθετημένου από λέξεις-κλειδιά. Είναι γνωστά μη-αγαπημένο από ελεγκτές κώδικα επειδή η κατάστασή του είναι σιωπηρή.
Δύο πρακτικές εναλλακτικές που ορισμένοι προτιμούν:
# Explicit state variable - equivalent semantics, easier to grep for:
my $in_block = 0;
while (<$fh>) {
$in_block = 1 if /^BEGIN/;
print if $in_block;
$in_block = 0 if /^END/;
}
# A simple two-step iterator:
while (<$fh>) {
if (/^BEGIN/ .. /^END/) { print }
}
Το flip-flop κερδίζει σε συντομία· η ρητή μορφή κερδίζει σε σαφήνεια με κόστος τρεις παραπάνω γραμμές. Επιλέξτε ανάλογα με το κοινό.
Δείτε επίσης#
reverse,grep,map- τελεστές λίστας που συνήθως συντίθενται με εύρη.Subscript - οι τομές πίνακα
@arr[1..3]βασίζονται στο εύρος σε περιβάλλον λίστας.Precedence - οι
..και...βρίσκονται στη γραμμή 17, μεταξύ||///και?:. Σχεδόν πάντα βάζετε παρενθέσεις όταν συνδυάζετε με λογική.