Βαθμωτά και συμβολοσειρές

substr#

Εξαγωγή, αντικατάσταση ή ψευδωνυμοποίηση μιας συνεχόμενης φέτας μιας συμβολοσειράς.

Η substr επιλέγει μια σειρά χαρακτήρων από την EXPR ξεκινώντας στο OFFSET και εκτείνεται σε LENGTH χαρακτήρες, και επιστρέφει αυτή τη φέτα. Η ίδια κλήση μπορεί επίσης να τροποποιήσει την αρχική συμβολοσειρά με τρεις διακριτούς τρόπους: ως lvalue αριστερά του =, μέσω της μορφής τεσσάρων ορισμάτων REPLACEMENT, ή μέσω ψευδωνυμοποιημένης lvalue αποθηκευμένης σε μεταβλητή που παρακολουθεί τη φέτα σε επόμενες εγγραφές. Ο χαρακτήρας μηδέν είναι ο πρώτος χαρακτήρας. Αρνητικό OFFSET μετρά από το τέλος· αρνητικό LENGTH σταματά τόσους χαρακτήρες πριν το τέλος. Αν παραλειφθεί το LENGTH, η φέτα τρέχει έως το τέλος της συμβολοσειράς.

Σύνοψη#

substr EXPR, OFFSET
substr EXPR, OFFSET, LENGTH
substr EXPR, OFFSET, LENGTH, REPLACEMENT
substr(EXPR, OFFSET, LENGTH) = NEWVALUE       # lvalue form

Τι επιστρέφεται#

Σε θέση rvalue, ένα νέο βαθμωτό που περιέχει την εξαγμένη φέτα. Σε θέση lvalue, ένα μαγικό βαθμωτό που, όταν του εκχωρείται τιμή, εμβολιάζει τη νέα τιμή στην EXPR στην καταγεγραμμένη θέση - το επιστρεφόμενο βαθμωτό δεν κρατά αντίγραφο των αρχικών χαρακτήρων. Η μορφή τεσσάρων ορισμάτων εκχωρεί το REPLACEMENT στην EXPR επιτόπου και επιστρέφει την υποσυμβολοσειρά που υπήρχε πριν, οπότε η εξαγωγή και η αντικατάσταση συμβαίνουν σε μία κλήση.

Αν το ζητούμενο εύρος βρίσκεται μερικώς εκτός της συμβολοσειράς, επιστρέφει μόνο το εντός-ορίων τμήμα. Αν βρίσκεται εξ ολοκλήρου εκτός της συμβολοσειράς, οι μορφές rvalue επιστρέφουν undef και προειδοποιούν· οι μορφές lvalue εγείρουν εξαίρεση.

Καθολική κατάσταση που επηρεάζει#

Καμία. Η substr είναι καθαρή ως προς τις καθολικές του διερμηνέα. Δεν διαβάζει ούτε γράφει στην $_, $/, $\, $!, ή σε οποιαδήποτε άλλη ειδική μεταβλητή. Οι προειδοποιήσεις για πρόσβαση εκτός εύρους διέπονται από τη συνήθη εμβέλεια use warnings / $^W.

Θέσεις και αρνητικοί δείκτες#

Το OFFSET μετριέται από την αρχή της συμβολοσειράς όταν είναι μη αρνητικό, και από το τέλος όταν είναι αρνητικό: το -1 είναι η θέση του τελευταίου χαρακτήρα, το -2 του προτελευταίου, και ούτω καθεξής.

Το LENGTH, όταν είναι μη αρνητικό, είναι ο αριθμός των χαρακτήρων προς συμπερίληψη. Όταν είναι αρνητικό, είναι δεξιά άγκυρα: η φέτα σταματά τόσους χαρακτήρες πριν το τέλος της συμβολοσειράς. Η παράλειψη του LENGTH είναι το ίδιο με «έως το τέλος».

my $s = "The black cat climbed the green tree";
my $color  = substr $s, 4, 5;       # "black"
my $middle = substr $s, 4, -11;     # "black cat climbed the"
my $end    = substr $s, 14;         # "climbed the green tree"
my $tail   = substr $s, -4;         # "tree"
my $z      = substr $s, -4, 2;      # "tr"

Χρήση της substr ως lvalue#

Αν η ίδια η EXPR είναι lvalue, η substr(EXPR, OFFSET, LENGTH) μπορεί να εμφανιστεί στην αριστερή πλευρά μιας εκχώρησης. Η δεξιά τιμή αντικαθιστά τη φέτα. Η αντικατάσταση δεν χρειάζεται να ταιριάζει με το LENGTH: μια μικρότερη αντικατάσταση μικραίνει τη συμβολοσειρά, μια μεγαλύτερη την επεκτείνει.

my $name = 'fred';
substr($name, 0, 2) = 'SH';         # $name is now "SHed"
substr($name, 1, 2) = 'ayfiel';     # $name is now "Shayfield"

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

my $name = 'fred';
substr($name, 4) = 'dy';            # $name is now "freddy"
substr($name, 7) = 'gap';           # exception

Για να διατηρήσετε σταθερό το μήκος της συμβολοσειράς, γεμίστε ή αποκόψτε ρητά την αντικατάσταση - για παράδειγμα με sprintf "%-*s", $len, $val.

Η μορφή αντικατάστασης τεσσάρων ορισμάτων#

Η substr EXPR, OFFSET, LENGTH, REPLACEMENT αντικαθιστά τη φέτα επιτόπου και επιστρέφει την υποσυμβολοσειρά που υπήρχε εκεί. Αυτή συνήθως προτιμάται από τη μορφή lvalue: η λειτουργία είναι μία έκφραση, και η παλιά τιμή είναι διαθέσιμη ως τιμή επιστροφής.

my $s = "The black cat climbed the green tree";
my $z = substr $s, 14, 7, "jumped from";    # $z is "climbed"
# $s is now "The black cat jumped from the green tree"

Αυτό αντικατοπτρίζει το ιδίωμα εξαγωγής-και-αντικατάστασης της splice σε πίνακες.

Το τέχνασμα της ψευδωνυμοποιημένης lvalue#

Το βαθμωτό που επιστρέφει η μορφή τριών ορισμάτων δεν είναι αντίγραφο των χαρακτήρων - είναι ένα μαγικό αντικείμενο που θυμάται σε ποια περιοχή της αρχικής συμβολοσειράς αναφέρεται. Η αποθήκευση αυτής της lvalue σε μεταβλητή (μέσω for, ή \ που λαμβάνεται μέσω accessor lvalue) επιτρέπει σε επαναλαμβανόμενες εγγραφές να εμβολιάζουν στην ίδια θέση της αρχικής συμβολοσειράς, ακόμη και καθώς η συμβολοσειρά αυτή αλλάζει μέγεθος:

my $x = '1234';
for (substr($x, 1, 2)) {
    $_ = 'a';    print $x, "\n";    # 1a4
    $_ = 'xyz';  print $x, "\n";    # 1xyz4
    $x = '56789';
    $_ = 'pq';   print $x, "\n";    # 5pq9
}

Με αρνητικό OFFSET, το ψευδώνυμο παρακολουθεί το τέλος της συμβολοσειράς:

my $x = '1234';
for (substr($x, -3, 2)) {
    $_ = 'a';    print $x, "\n";    # 1a4
    $x = 'abcdefg';
    print $_, "\n";                 # f
}

Αυτό είναι χρήσιμο όταν επανεγγράφετε επανειλημμένα την ίδια θέση ενός buffer (π.χ. πεδία επικεφαλίδας σε εγγραφή σταθερής διάταξης) - αλλά είναι επίσης κλασική πηγή εκπλήξεων. Προτιμήστε τη μορφή τεσσάρων ορισμάτων εκτός αν θέλετε συγκεκριμένα την ψευδωνυμοποίηση.

Παραδείγματα#

Εξαγωγή σταθερού πεδίου από εγγραφή:

my $line = "2026-04-22  richard.jelinek\@example.com";
my $date = substr $line, 0, 10;         # "2026-04-22"

Αφαίρεση αρχικού προθέματος γνωστού μήκους:

my $msg = "ERROR: disk full";
my $rest = substr $msg, length("ERROR: ");   # "disk full"

Αντικατάσταση σταθερού πεδίου επιτόπου με τη μορφή τεσσάρων ορισμάτων, διατηρώντας την παλιά τιμή:

my $record = "name:       John      age: 42";
my $old    = substr $record, 12, 10, sprintf("%-10s", "Jane");
# $record is now "name:       Jane      age: 42"
# $old is "John      "

Διάσχιση συμβολοσειράς σε παράθυρα τριών χαρακτήρων χωρίς αντιγραφή ολόκληρης της συμβολοσειράς κάθε φορά:

my $s = "ABCDEFGH";
for (my $i = 0; $i + 3 <= length $s; $i++) {
    print substr($s, $i, 3), "\n";  # ABC BCD CDE DEF ...
}

Επανεγγραφή του τελευταίου byte ενός buffer επανειλημμένα μέσω ψευδωνυμοποιημένης lvalue:

my $buf = "packet: 0";
my $tail = \substr($buf, -1, 1);
$$tail = '1';  # $buf is now "packet: 1"
$$tail = '2';  # $buf is now "packet: 2"

Οριακές περιπτώσεις#

  • Rvalue εκτός εύρους, μερικώς εντός ορίων: επιστρέφει μόνο το εντός-ορίων τμήμα, καμία προειδοποίηση.

    my $s = "abcd";
    substr($s, 2, 100);                 # "cd"
    
  • Rvalue εκτός εύρους, εξ ολοκλήρου πέραν του τέλους: επιστρέφει undef και προειδοποιεί υπό use warnings. Η περίπτωση κενής ουράς (ακριβώς στο τέλος) επιστρέφει "" χωρίς προειδοποίηση:

    my $name = 'fred';
    my $null = substr $name, 4, 2;      # "" (no warning)
    my $oops = substr $name, 7;         # undef, with warning
    
  • Lvalue εκτός εύρους: εγείρει εξαίρεση. Η substr αρνείται να επεκτείνει σιωπηρά τη συμβολοσειρά με κενό απροσδιόριστου περιεχομένου.

  • Αρνητικό OFFSET μεγαλύτερο από τη συμβολοσειρά: μετρά ως «πριν την αρχή», και περικόπτεται στη θέση 0 στις τρέχουσες Perls· υπό use warnings αυτό εκπέμπει προειδοποίηση «substr outside of string» σε ορισμένες εκδόσεις. Προτιμήστε να περικόπτετε ρητά.

  • Αρνητικό LENGTH που υπερβαίνει την υπολειπόμενη ουρά: παράγει κενή συμβολοσειρά, επειδή η δεξιά άγκυρα πέφτει στην ή πριν την αριστερή άγκυρα.

    my $s = "abcde";
    substr($s, 1, -10);                 # ""
    
  • Unicode: η substr λειτουργεί σε χαρακτήρες, όχι bytes. Σε συμβολοσειρά με τη σημαία UTF-8 ενεργοποιημένη, οι θέσεις μετρούν codepoints· σε συμβολοσειρά bytes, οι θέσεις μετρούν bytes. Η ανάμειξη των δύο αντιμετωπίζοντας μια αποκωδικοποιημένη συμβολοσειρά ως buffer bytes παράγει λάθος offsets - αποκωδικοποιήστε πρώτα, και έπειτα ευρετηριάστε.

  • Δεσμευμένα ή μαγικά βαθμωτά: η lvalue substr τιμά τη μαγεία STORE-time στον στόχο, οπότε οι δεσμευμένες μεταβλητές βλέπουν ολόκληρη τη μεταλλαγμένη συμβολοσειρά, όχι τη φέτα.

  • Ψευδωνυμοποιημένη lvalue που διατηρείται πέρα από τη ζωή του στόχου της: αν η αρχική μεταβλητή εξέλθει της εμβέλειας ενώ το ψευδώνυμο εξακολουθεί να ζει, μεταγενέστερες εγγραφές μέσω του ψευδωνύμου ενεργούν σε ελευθερωμένη συμβολοσειρά· κρατήστε τη ζωή του ψευδωνύμου εντός εκείνης του στόχου.

  • Γωνία πριν την 5.10: επαναλαμβανόμενες εγγραφές μέσω μίας lvalue είχαν απροσδιόριστη συμπεριφορά σε παλαιότερες perls, όπως και τα αρνητικά offsets πριν την 5.16. Η σύγχρονη Perl (και η pperl) ακολουθούν τη σημασιολογία που τεκμηριώνεται σε αυτή τη σελίδα.

Διαφορές από το upstream#

Πλήρως συμβατό με το upstream Perl 5.42.

Δείτε επίσης#

  • index - εύρεση της θέσης μιας υποσυμβολοσειράς, για να τροφοδοτηθεί στην substr ως OFFSET

  • rindex - ίδιο, με αναζήτηση από τα δεξιά

  • length - το ανώτατο όριο σε οποιοδήποτε ουσιαστικό OFFSET ή LENGTH περνάτε στην substr

  • splice - το ανάλογο σε επίπεδο πίνακα της μορφής αντικατάστασης τεσσάρων ορισμάτων

  • pack / unpack - για εγγραφές σταθερής διάταξης όπου πολλά πεδία διαβάζονται ή επανεγγράφονται μονομιάς, προτιμήστε αυτές αντί μιας αλυσίδας κλήσεων substr

  • tr/// - μαζική αντικατάσταση σε επίπεδο χαρακτήρων που δεν χρειάζεται θεσιακούς δείκτες