Λίστες · Δεδομένα σταθερού μήκους

unpack#

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

Η unpack είναι το αντίστροφο της pack. Διασχίζει την EXPR από αριστερά προς τα δεξιά, καταναλώνοντας τα bytes που περιγράφει κάθε οδηγία στο TEMPLATE και μετατρέποντάς τα σε τιμές Perl. Το αποτέλεσμα είναι λίστα - μία τιμή ανά οδηγία, ή ανά επανάληψη όταν η οδηγία έχει μετρητή. Αν παραλειφθεί η EXPR, η unpack διαβάζει από την $_.

Αυτή η σελίδα είναι μια αναφορά οδηγιών. Για αφηγηματική εισαγωγή με λυμένα παραδείγματα πρωτοκόλλων και μορφών αρχείων, ξεκινήστε από τον οδηγό pack/unpack.

Σύνοψη#

unpack TEMPLATE, EXPR
unpack TEMPLATE                             # reads from $_
my @fields = unpack "A10 A10 A*", $line;
my ($ver, $len, $payload) = unpack "n N A*", $msg;

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

Μια λίστα τιμών, μία ανά οδηγία (ή ανά επανάληψη όταν η οδηγία έχει μετρητή). Σε βαθμωτό περιβάλλον, επιστρέφεται μόνο η πρώτη τιμή που παράχθηκε:

my @all   = unpack "A4 A4 A*", $rec;    # three values
my $first = unpack "A4 A4 A*", $rec;    # just the first - not a count

Κάθε οδηγία καθορίζει τον τύπο Perl του αποτελέσματός της - δείτε τη στήλη «Τύπος αποτελέσματος» στον πίνακα οδηγιών παρακάτω.

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

Το unpack TEMPLATE χωρίς EXPR διαβάζει την $_. Καμία άλλη καθολική του διερμηνέα δεν συμβουλεύεται. Οι οδηγίες C0 / U0 αλλάζουν τοπικά εντός του προτύπου την ερμηνεία byte-έναντι-χαρακτήρα, αλλά δεν μεταβάλλουν κάποια εξωτερική κατάσταση.

Σύνταξη προτύπου#

Πανομοιότυπη με αυτή της pack: ακολουθία γραμμάτων-οδηγιών, προαιρετικά ακολουθούμενη από μετρητές επανάληψης N / * / […] και τροποποιητές ! / < / >. Οι παρενθέσεις σχηματίζουν ομάδες· το # εισάγει σχόλιο προτύπου. Δείτε την pack για τους πλήρεις κανόνες σύνταξης - αυτή η σελίδα καλύπτει μόνο τη σημασιολογία που είναι ειδική για την unpack.

Πίνακας οδηγιών#

Όλες οι οδηγίες της unpack σε ένα μέρος. Το W είναι το πλάτος σε bytes που καταναλώνεται από την είσοδο ανά παραγόμενο βαθμωτό.

Οδηγία

W

Προσημασμένο

Endian

Τύπος αποτελέσματος

Τροποποιητές

Σημειώσεις

a

μετρητής

-

-

συμβολοσειρά

-

Επιστρέφει τα bytes ανέγγιχτα

A

μετρητής

-

-

συμβολοσειρά

-

Αφαιρεί τους τελικούς λευκούς χαρακτήρες και τα NUL

Z

μετρητής

-

-

συμβολοσειρά

-

Επιστρέφει τα πάντα μέχρι το πρώτο NUL

b

μετρητής/8

-

-

συμβολοσειρά bits

-

Χαρακτήρες «0»/»1», LSB κάθε byte πρώτο

B

μετρητής/8

-

-

συμβολοσειρά bits

-

Χαρακτήρες «0»/»1», MSB κάθε byte πρώτο

h

μετρητής/2

-

-

δεκαεξαδική συμβολοσειρά

-

Χαρακτήρες [0-9a-f], κάτω nybble πρώτο

H

μετρητής/2

-

-

δεκαεξαδική συμβολοσειρά

-

Χαρακτήρες [0-9a-f], άνω nybble πρώτο

c

1

ναι

-

ακέραιος

-

Προσημασμένο char

C

1

όχι

-

ακέραιος

-

Μη προσημασμένο char

W

1

όχι

-

ακέραιος

-

Μη προσημασμένο char· αποδίδει σημείο κώδικα σε κατάσταση U0

s

2

ναι

native

ακέραιος

! < >

s! = native short

S

2

όχι

native

ακέραιος

! < >

S! = native unsigned short

l

4

ναι

native

ακέραιος

! < >

l! = native long

L

4

όχι

native

ακέραιος

! < >

L! = native unsigned long

i

native

ναι

native

ακέραιος

! < >

sizeof(int)

I

native

όχι

native

ακέραιος

! < >

sizeof(unsigned int)

q

8

ναι

native

ακέραιος

< >

Απαιτεί Perl με 64-bit ακεραίους

Q

8

όχι

native

ακέραιος

< >

Απαιτεί Perl με 64-bit ακεραίους

n

2

όχι

big

ακέραιος

!

Σειρά δικτύου· n! = προσημασμένο

N

4

όχι

big

ακέραιος

!

Σειρά δικτύου· N! = προσημασμένο

v

2

όχι

little

ακέραιος

!

Σειρά «VAX»· v! = προσημασμένο

V

4

όχι

little

ακέραιος

!

Σειρά «VAX»· V! = προσημασμένο

j

μέγεθος IV

ναι

native

ακέραιος

< >

Εσωτερική IV της Perl

J

μέγεθος UV

όχι

native

ακέραιος

< >

Εσωτερική UV της Perl

f

4

-

native

αριθμός

< >

IEEE 754 απλής ακρίβειας

d

8

-

native

αριθμός

< >

IEEE 754 διπλής ακρίβειας

F

μέγεθος NV

-

native

αριθμός

< >

Εσωτερικός float της Perl

D

ποικίλλει

-

native

αριθμός

< >

Long double

p

μέγεθος ptr

-

native

συμβολοσειρά

< >

Αποαναφέρει δείκτη σε συμβολοσειρά τερματισμένη με NUL

P

μέγεθος ptr

-

native

συμβολοσειρά

< >

Αποαναφέρει δείκτη· μετρητής = bytes προς ανάγνωση

u

ποικίλλει

-

-

συμβολοσειρά

-

Bytes αποκωδικοποιημένα με uudecode

U

ποικίλλει

-

-

ακέραιος

-

Αριθμός σημείου κώδικα Unicode

w

ποικίλλει

όχι

-

ακέραιος

-

Ακέραιος συμπιεσμένος κατά BER

x

1

-

-

(κανένας)

!

Παρακάμπτει ένα byte προς τα εμπρός· το x!N ευθυγραμμίζει προς τα εμπρός

X

−1

-

-

(κανένας)

!

Επιστροφή κατά ένα byte· το X!N ευθυγραμμίζει προς τα πίσω

@

απόλυτο

-

-

(κανένας)

!

Μετάβαση στη θέση N εντός της εσώτερης ομάδας

.

-

-

-

ακέραιος

!

Επιστρέφει την τρέχουσα θέση (σχετική με την αρχή της ομάδας / συμβολοσειράς)

( )

-

-

-

-

< > !

Ομάδα: ο μετρητής επανάληψης και η endianness διαδίδονται προς τα μέσα

/

-

-

-

-

-

Δείτε «Φορτία με πρόθεμα μήκους» παρακάτω

%N

ποικίλλει

-

-

ακέραιος

-

Πρόθεμα. Άθροισμα ελέγχου N-bit των τιμών της επόμενης οδηγίας

Οι τροποποιητές έχουν την ίδια σημασία όπως στην pack: το ! επιλέγει native μεγέθη, σημασιολογία ευθυγράμμισης, προσήμανση για τα n / N / v / V, ή μετατοπίσεις σε bytes για τα @ / .· τα < / > εξαναγκάζουν endianness.

Διαφορές από την pack#

  • Το a δεν αφαιρεί τίποτα (επιστρέφει τα bytes ωμά)· το A αφαιρεί τους τελικούς λευκούς χαρακτήρες και τα NUL· το Z σταματά στο πρώτο NUL. Με την pack και τα τρία συμπληρώνουν· με την unpack και τα τρία αφαιρούν συμπλήρωση με διαφορετικό τρόπο.

  • Το x παρακάμπτει προς τα εμπρός κατά W, το X επιστρέφει κατά W. Το X πριν την αρχή της συμβολοσειράς είναι μοιραίο σφάλμα.

  • Το / διαβάζει μετρητή από τα δεδομένα και τον εφαρμόζει στην επόμενη οδηγία:

    unpack("W/a", "\004Gurusamy")          # ("Guru")
    unpack("a3/A A*", "007 Bond  J ")      # (" Bond", "J")
    unpack("n/a*", "\x00\x0chello, world") # ("hello, world")
    

    Με την pack η μορφή είναι length-item/item και το μήκος υπολογίζεται από το μήκος της τιμής. Με την unpack η μορφή είναι /item (χωρίς length-item πριν) - η προηγούμενη ακέραια οδηγία παρέχει τον μετρητή.

  • Το %N είναι αποκλειστικό της unpack. Αντικαθιστά την κανονική έξοδο της επόμενης οδηγίας με το άθροισμα N-bit των τιμών που θα είχε αλλιώς παραγάγει αυτή η οδηγία. Το %32W* είναι το άθροισμα ελέγχου sum του System V. Το %32b* μετρά τα ενεργοποιημένα bits.

  • Το . επιστρέφει την τρέχουσα θέση byte αντί να συμπληρώνει με μηδενικά μέχρι μία. Χρήσιμο μετά από πλοήγηση x / X για να μάθετε πού βρίσκεστε.

  • Τα p και P αποαναφέρουν δείκτες που διαβάζονται από την είσοδο - σχεδόν πάντα μη ασφαλές εκτός αν γνωρίζετε ότι η είσοδος παράχθηκε από pack "p" / pack "P" στην ίδια διεργασία.

  • Συμπεριφορά under-run / over-run: αν το πρότυπο ζητά περισσότερα δεδομένα από όσα περιέχει η EXPR, το αποτέλεσμα δεν είναι καλά ορισμένο (μπορεί να αποδώσει κενές συμβολοσειρές, μηδενικά, μειωμένο μετρητή επανάληψης, ή εξαίρεση). Αν η EXPR είναι μακρύτερη από όσο καταναλώνει το πρότυπο, τα τελικά bytes αγνοούνται σιωπηλά.

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

Ανάλυση μιας ελάχιστης κεφαλίδας δυαδικού πρωτοκόλλου - έκδοση 16-bit, μήκος 32-bit, στη συνέχεια φορτίο μεταβλητού μήκους, όλα σε σειρά bytes δικτύου:

my ($ver, $len, $payload) = unpack "n N A*", $msg;

Διαχωρισμός εγγραφής κειμένου σταθερού πλάτους - γρηγορότερος και πιο καθαρός από αλυσιδωμένες κλήσεις substr:

my ($date, $desc, $amount) = unpack "A10 A27 A*", $line;
# "2026-04-22 coffee at the station           3.50"
# $date = "2026-04-22", $desc = "coffee at the station",
# $amount = "3.50"

Εξαγωγή αθροίσματος ελέγχου τύπου System V με το πρόθεμα % - το 32-bit άθροισμα κάθε byte, μασκαρισμένο σε 16 bits:

my $checksum = do {
    local $/;                           # slurp
    unpack "%32W*", readline $fh;
} % 65535;

Μέτρηση ενεργοποιημένων bits σε διάνυσμα bits - το %32b* διαβάζει ολόκληρη τη μάσκα ως bits και επιστρέφει το άθροισμά τους:

my $setbits = unpack "%32b*", $selectmask;

Ανάγνωση ακολουθίας little-endian 32-bit ακεραίων από ωμό ενταμιευτή:

my @ints = unpack "V*", $buf;

Χρησιμοποιήστε το x για να παρακάμψετε bytes πλήρωσης, το X για να επιστρέψετε μετά από peek:

# 2-byte tag, skip 2 reserved bytes, then 4 32-bit big-endian values
my ($tag, @vals) = unpack "n x2 N4", $frame;

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

  • Το βαθμωτό περιβάλλον επιστρέφει μόνο την πρώτη τιμή. Η ανάθεση της unpack σε βαθμωτό σχεδόν ποτέ δεν είναι αυτό που θέλετε. Για να μετρήσετε πεδία, αναθέστε πρώτα σε λίστα, ή χρησιμοποιήστε () = unpack ... σε περιβάλλον λίστας:

    my $n = () = unpack "A10 A10 A*", $line;   # 3
    
  • Το * είναι άπληστο, όχι placeholder. Το A* καταναλώνει όλα τα υπόλοιπα bytes ως μία συμβολοσειρά· δεν υπάρχει οπισθοχώρηση. Μια οδηγία * πρέπει να είναι η τελευταία στην ακολουθία της, διαφορετικά τίποτα μετά από αυτή δεν εκτελείται.

  • Τα πρότυπα δεν είναι κανονικές εκφράσεις. Οι λευκοί χαρακτήρες αγνοούνται, αλλά δεν υπάρχει εναλλαγή, ούτε |, ούτε lookahead. Αν το σχήμα των δεδομένων εξαρτάται από προηγούμενα πεδία, κάντε unpack σε στάδια: αποκωδικοποιήστε μια κεφαλίδα, μετά καλέστε ξανά την unpack πάνω στο φορτίο χρησιμοποιώντας πρότυπο παραγόμενο από αυτό που μόλις διαβάσατε.

  • Σημασιολογία byte έναντι χαρακτήρα. Η unpack τρέχει σε κατάσταση byte προεπιλεγμένα πάνω σε συμβολοσειρά bytes, και σε κατάσταση χαρακτήρα σε συμβολοσειρά με σημαία UTF-8 τεθειμένη. Το C0 εξαναγκάζει σε κατάσταση byte από εκείνο το σημείο· το U0 εξαναγκάζει σε κατάσταση UTF-8. Η ανάμειξη συμβολοσειράς σημαδεμένης ως UTF-8 με αριθμητικές οδηγίες όπως N διαβάζει σημεία κώδικα, όχι bytes - συνήθως όχι αυτό που θέλετε. Καλέστε πρώτα την utf8::encode, ή λειτουργήστε πάνω σε δεδομένα επιπέδου byte.

  • Το X πριν την αρχή της συμβολοσειράς είναι μοιραίο.

  • Τα p / P σε αυθαίρετη είσοδο αποτελούν απροσδιόριστη συμπεριφορά. Μην τα χρησιμοποιείτε ποτέ σε δεδομένα που δεν έχετε πακετάρει εσείς οι ίδιοι στην ίδια διεργασία.

  • Χωρίς όρισμα EXPR: το unpack TEMPLATE διαβάζει την $_. Χρήσιμο μέσα σε βρόχους while (<$fh>) { ... } πάνω από εγγραφές σταθερού πλάτους.

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

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

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

  • pack - η αντίστροφη λειτουργία· ίδια γλώσσα προτύπων

  • substr - εξαγωγή μίας σταθερής τομής· απλούστερη για ένα πεδίο, βραδύτερη για πολλά

  • sprintf - πλήρης κύκλος μεταξύ δυαδικού και αναγνώσιμου από άνθρωπο

  • read - διαβάζει ωμά bytes από filehandle σε ενταμιευτή για την unpack

  • vec - προσπελάσιμη κατά δείκτη πρόσβαση σε διάνυσμα bits χωρίς πρότυπο

  • Οδηγός pack/unpack - προσανατολισμένη σε εργασίες περιδιάβαση με λυμένα παραδείγματα πρωτοκόλλων και μορφών αρχείων