Κανονικές εκφράσεις και αντιστοίχιση μοτίβων

s///#

Αναζητά σε μια συμβολοσειρά ένα μοτίβο και αντικαθιστά κάθε αντιστοιχία με ένα κείμενο αντικατάστασης.

Ο s/// είναι ο τελεστής αντικατάστασης της Perl. Εντοπίζει κείμενο που ταιριάζει με το PATTERN στη συμβολοσειρά-στόχο, αντικαθιστά κάθε αντιστοιχία με το REPLACEMENT, και εξ ορισμού επιστρέφει τον αριθμό των αντικαταστάσεων που έγιναν. Χωρίς ρητό στόχο (χωρίς =~ ή !~), λειτουργεί επί του $_. Ο στόχος πρέπει να είναι βαθμωτό lvalue - μεταβλητή, στοιχείο πίνακα ή hash, ή substr / ανάθεση που παράγει ένα - εκτός αν χρησιμοποιηθεί η σημαία /r, η οποία λειτουργεί σε οποιαδήποτε τιμή και επιστρέφει το τροποποιημένο αντίγραφο.

Σύνοψη#

s/PATTERN/REPLACEMENT/FLAGS
$str =~ s/PATTERN/REPLACEMENT/FLAGS
$str !~ s/PATTERN/REPLACEMENT/FLAGS
my $copy = $str =~ s/PATTERN/REPLACEMENT/r

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

Εξ ορισμού, το πλήθος των αντικαταστάσεων που πραγματοποιήθηκαν ως ακέραιος: 0 όταν τίποτα δεν ταίριαξε (το οποίο είναι ψευδές σε λογικό περιβάλλον), θετικός ακέραιος σε επιτυχία. Το βαθμωτό-στόχος τροποποιείται επιτόπια.

Με τη σημαία /r, η σημασιολογία αντιστρέφεται: ο στόχος δεν τροποποιείται, και ο τελεστής επιστρέφει τη (πιθανώς αλλαγμένη) συμβολοσειρά. Αν τίποτα δεν ταίριαξε, το /r εξακολουθεί να επιστρέφει αντίγραφο του πρωτοτύπου. Το αποτέλεσμα του /r είναι πάντα απλή συμβολοσειρά, ακόμη και όταν η πηγή είναι tied μεταβλητή ή blessed αντικείμενο με υπερφόρτωση.

Το !~ αντιστρέφει τη λογική έννοια της τιμής επιστροφής: αποδίδει αληθές όταν δεν έγινε καμία αντικατάσταση, ψευδές όταν έγινε τουλάχιστον μία αντικατάσταση. Ο στόχος εξακολουθεί να τροποποιείται και στις δύο περιπτώσεις.

my $n = ($text =~ s/foo/bar/g);     # count of replacements
my $out = $text =~ s/foo/bar/r;     # copy-and-modify, $text untouched

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

  • $_ - ο προεπιλεγμένος στόχος όταν δεν δίνεται =~ ή !~. Το s/old/new/ χωρίς σύνδεση διαβάζει και γράφει το $_.

  • Τα $&, [`$``](../perlvar), [`$”`](../perlvar), [`$1`](../perlvar) και τα όμοιά τους - ορίζονται από κάθε επιτυχημένη αντιστοιχία, ακριβώς όπως τα ορίζει η [`m//`](m). Μέσα στο `REPLACEMENT` αναφέρονται στην τρέχουσα αντιστοιχία, όχι σε προηγούμενη.

  • pos - εκκαθαρίζεται στο βαθμωτό-στόχο από μια επιτυχημένη μη-/g αντικατάσταση· υπό το /g προχωρά με κάθε αντιστοιχία και μπορεί να ελεγχθεί μεταξύ επαναλήψεων.

  • Το τελευταίο επιτυχημένο μοτίβο - χρησιμοποιείται όταν το PATTERN αξιολογείται στην κενή συμβολοσειρά (το s//new/ επαναχρησιμοποιεί την τελευταία επιτυχημένη regex από αυτή την εμβέλεια).

  • Τα $/, $\ και οι διαχωριστές εξόδου δεν επηρεάζονται - το s/// παράγει συμβολοσειρά, δεν γράφει.

Σημαίες#

Το πλήρες σύνολο είναι msixpodualngcer. Οι σημαίες πλευράς αντιστοίχισης συμπεριφέρονται ακριβώς όπως στα m// και qr· δείτε το κεφάλαιο τροποποιητών του οδηγού regex για τις λεπτομέρειες πλευράς αντιστοίχισης. Σημαίες ειδικές για την αντικατάσταση:

  • e - αξιολογεί το REPLACEMENT ως μπλοκ κώδικα Perl. Η τιμή του μπλοκ είναι η συμβολοσειρά αντικατάστασης. Ισοδύναμο με την περιτύλιξή του σε do { ... } και τη συμβολοσειροποίηση του αποτελέσματος.

  • ee - αξιολογεί ως κώδικα, και έπειτα κάνει eval την προκύπτουσα συμβολοσειρά ξανά. Ισοδύναμο με eval(do { REPLACEMENT }). Επιπλέον τροποποιητές e προσθέτουν περισσότερα στρώματα eval.

  • r - μη καταστροφικό: αφήνει τον στόχο αμετάβλητο και επιστρέφει το τροποποιημένο αντίγραφο (ή αμετάβλητο αντίγραφο σε περίπτωση μη αντιστοιχίας). Δεν μπορεί να συνδυαστεί με τον περιορισμό μη-βαθμωτού lvalue στόχου - οποιαδήποτε έκφραση είναι έγκυρος στόχος υπό το /r.

  • g - καθολικό: αντικαθιστά κάθε μη επικαλυπτόμενη αντιστοιχία, όχι μόνο την πρώτη.

  • c - γίνεται δεκτό για συντακτική συμμετρία με τη m// αλλά δεν έχει επίδραση στη συμπεριφορά του s///· ενεργοποιεί προειδοποίηση υπό το use warnings.

Σημαίες πλευράς αντιστοίχισης σε μία γραμμή: m (πολυγραμμικά ^/$), s (το . αντιστοιχίζει νέα γραμμή), i (χωρίς διάκριση πεζών-κεφαλαίων), x / xx (εκτεταμένα κενά, σχόλια), p (διατηρεί τις μεταβλητές αντιστοίχισης· παρωχημένο από την 5.20), o (μεταγλώττιση μοτίβου μία φορά), d / u / a / l (σημασιολογία συνόλου χαρακτήρων), n (μη συλλαμβάνον εξ ορισμού). Δείτε το κεφάλαιο τροποποιητών.

Οριοθέτες#

Οποιοσδήποτε χαρακτήρας που δεν είναι λευκός μπορεί να αντικαταστήσει το /. Αν ο επιλεγμένος οριοθέτης είναι ένας από τους (, [, {, ή <, ο τελεστής λαμβάνει δύο ομάδες σε αγκύλες και ο οριοθέτης μεταξύ τους είναι προαιρετικός:

s(foo)(bar)
s{foo}{bar}
s<foo>/bar/
s[foo]{bar}g

Οι οριοθέτες με μονά εισαγωγικά απενεργοποιούν την παρεμβολή τόσο στο PATTERN όσο και στο REPLACEMENT (εκτός αν ισχύει το /e, το οποίο αναλύει πάντα το REPLACEMENT ως κώδικα):

s'$name'$value';    # literal $name → literal $value, no interpolation

Τα backticks είναι κανονικοί οριοθέτες· το s`x`y` δεν εκτελεί εντολή κελύφους.

Όταν ο οριοθέτης είναι χαρακτήρας που είναι επίσης χαρακτήρας προσδιοριστή, απαιτείται κενό μετά το s ώστε ο αναλυτής να μη το διαβάσει ως μέρος του ονόματος του τελεστή.

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

Βασική επιτόπια αντικατάσταση στο $_:

$_ = 'the quick brown fox';
s/quick/slow/;                  # $_ is now 'the slow brown fox'

Ρητός στόχος με =~:

my $path = '/usr/bin/perl';
$path =~ s|/usr/bin|/usr/local/bin|;
# $path is '/usr/local/bin/perl'

Καθολική αντικατάσταση, με σύλληψη του πλήθους:

my $text = 'one two two three two';
my $n = ($text =~ s/two/2/g);   # $text: 'one 2 2 three 2'; $n == 3

Μη καταστροφικό /r - αφήνει την πηγή ως έχει, επιστρέφει το αντίγραφο. Ιδιωματικό σε map:

my @clean = map { s/\s+\z//r } @lines;   # @lines untouched

Αξιολόγηση κώδικα με /e. Η δεξιά πλευρά είναι έκφραση Perl της οποίας η τιμή γίνεται η αντικατάσταση:

my $s = 'abc123xyz';
$s =~ s/\d+/$& * 2/e;           # $s is 'abc246xyz'

my %percent = (n => "\n", t => "\t");
$s =~ s/%(.)/$percent{$1} || $&/ge;     # expand %-escapes

Αλυσιδωτό /r - καθαρά συναρτησιακοί μετασχηματισμοί χωρίς ενδιάμεση μεταβλητή:

my $out = $text =~ s/foo/bar/r
                =~ s/baz/qux/r;

Ομάδες σύλληψης και οπισθαναφορές στην αντικατάσταση - προσέξτε τη μορφή $1, όχι \1:

# swap the first two whitespace-separated fields
s/(\S+)\s+(\S+)/$2 $1/;

Ο ιδιωματισμός 1 while για αντικαταστάσεις που δημιουργούν νέες αντιστοιχίες:

# insert commas into an integer from the right
my $n = '1234567890';
1 while $n =~ s/(\d)(\d\d\d)(?!\d)/$1,$2/;
# $n is '1,234,567,890'

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

  • Ο στόχος πρέπει να είναι βαθμωτό lvalue (εκτός αν χρησιμοποιείται το /r): μεταβλητή, στοιχείο, ή lvalue της substr. Το s/x/y/ έναντι κυριολεκτικής συμβολοσειράς ή του αποτελέσματος μιας κλήσης συνάρτησης είναι σφάλμα κατά τη μεταγλώττιση. Υπό το /r οποιαδήποτε έκφραση είναι επιτρεπτή αφού τίποτα δεν τροποποιείται.

  • Το κενό μοτίβο επαναχρησιμοποιεί την τελευταία επιτυχημένη αντιστοιχία. Το s//new/ αντικαθιστά έναντι όποιου PATTERN ταίριαξε πιο πρόσφατα στην περικλείουσα εμβέλεια. Βολικό μέσα σε while (m/.../g) { s//x/ }, εκπληκτικό όταν έχει εκτελεστεί άσχετος κώδικας ενδιάμεσα.

  • Η παρεμβολή συμβαίνει κατά τον χρόνο εκτέλεσης. Το s/$foo/$bar/ επανα-μεταγλωττίζει το μοτίβο σε κάθε κλήση αν το $foo αλλάξει. Χρησιμοποιήστε /o για μεταγλώττιση μία φορά και πάγωμα της συλληφθείσας τιμής - ή προμεταγλωττίστε με qr, που είναι η σύγχρονη εναλλακτική.

  • Το /e αναλύει την αντικατάσταση κατά τη μεταγλώττιση παρόλο που εκτελείται κατά τη στιγμή της αντιστοίχισης. Τα συντακτικά σφάλματα εμφανίζονται κατά τη φόρτωση του σεναρίου, όχι όταν πυροδοτείται η αντικατάσταση. Κάθε επιπλέον e τυλίγει μία ακόμη eval γύρω από την τιμή.

  • Το /g με κενή αντιστοιχία προχωρά κατά έναν χαρακτήρα για να αποφευχθεί άπειρος βρόχος: το s/\b/-/g εισάγει μεταξύ κάθε λεκτικού, δεν κολλάει στην πρώτη θέση.

  • Το !~ αντιστρέφει την επιστροφή, όχι την εργασία. Το $x !~ s/A/a/g εξακολουθεί να τροποποιεί το $x· απλώς επιστρέφει αληθές όταν δεν βρέθηκε κανένα A.

  • Η αντιστοίχιση οριοθετών για αγκύλες χρησιμοποιεί τον κατοπτρικό αντίστοιχο: s{pat}{rep}, s<pat><rep>. Ένας οριοθέτης διαφορετικός από αγκύλη πρέπει να εμφανιστεί τρεις φορές συνολικά: s/pat/rep/.

  • Το /c είναι no-op στο s///. Γίνεται δεκτό για συντακτική συμμετρία με τη m//· η χρήση του παράγει προειδοποίηση υπό το use warnings και τίποτε άλλο.

  • Ιδιωματισμός ανάθεσης-ως-στόχου. Το ($copy = $src) =~ s/x/y/g γεμίζει το $copy με την τροποποιημένη τιμή και αφήνει το $src ως έχει. Ο σύγχρονος κώδικας προτιμά το my $copy = $src =~ s/x/y/gr.

  • Στόχοι tied ή υπερφορτωμένοι. Χωρίς το /r, καλείται η STORE μετά την αντικατάσταση για να γραφεί η νέα τιμή πίσω· η ανακτημένη τιμή αντιγράφεται σε απλό ενταμιευτή πριν εφαρμοστεί το μοτίβο. Με το /r το αποτέλεσμα είναι πάντα απλή συμβολοσειρά - η tie / υπερφόρτωση δεν διατηρείται στην επιστροφή.

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

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

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

  • m// - ο τελεστής αντιστοίχισης· μοιράζεται τη σημασιολογία σημαιών πλευράς αντιστοίχισης και τους κανόνες επιστροφής έναντι περιβάλλοντος

  • tr/// - μεταγραμματισμός χαρακτήρα προς χαρακτήρα· πολύ ταχύτερος όταν η εργασία είναι κυριολεκτική μετάφραση χαρακτήρων, όχι regex

  • qr// - προμεταγλωττίζει ένα μοτίβο μία φορά και το παρεμβάλλει σε πολλές κλήσεις s/// ή m//· η σύγχρονη εναλλακτική για το /o

  • split - όταν ο στόχος είναι το σπάσιμο μιας συμβολοσειράς σε ένα μοτίβο αντί για αντικατάσταση αντιστοιχιών, καταφύγετε στη split

  • Substitution chapter

    • the chapter dedicated to s///; covers /e, /r, /g, \K, and zero-length-match handling

  • Regular expressions guide

    • the full pattern-language reference; every match-side flag on s/// is defined there

  • $& - το κείμενο που ταίριαξε, διαθέσιμο μέσα στο REPLACEMENT κάθε s///