unpack#
חילוץ ערכים בעלי טיפוס ממחרוזת בינארית או באורך קבוע לפי תבנית.
unpack הוא ההפך של pack. הוא הולך לאורך EXPR משמאל לימין, צורך את הבתים המתוארים על־ידי כל הוראה ב־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 מחליפות פירוש בית־מול־תו של התבנית מקומית בתוך התבנית אך אינן משנות שום מצב חיצוני.
תחביר תבנית#
זהה ל־pack: רצף של אותיות הוראה, ואחריהן אופציונלית מוני חזרות N / * / […] ומתאמים ! / < / >. סוגריים יוצרים קבוצות; # מציג הערת תבנית. ראו pack לכללי התחביר המלאים - עמוד זה מכסה רק את הסמנטיקה הייחודית ל־unpack.
טבלת הוראות#
כל הוראת unpack במקום אחד. W הוא הרוחב בבתים הנצרך מהקלט לכל סקלר שמופק.
הוראה | W | עם סימן | Endian | טיפוס תוצאה | מתאמים | הערות |
|---|---|---|---|---|---|---|
| מונה | - | - | מחרוזת | - | מחזיר בתים ללא שינוי |
| מונה | - | - | מחרוזת | - | מסיר רווח לבן ו־ |
| מונה | - | - | מחרוזת | - | מחזיר את כל מה שעד ה־ |
| מונה/8 | - | - | מחרוזת ביטים | - | תווי ”0“/“1“, LSB של כל בית ראשון |
| מונה/8 | - | - | מחרוזת ביטים | - | תווי ”0“/“1“, MSB של כל בית ראשון |
| מונה/2 | - | - | מחרוזת הקסה | - | תווי |
| מונה/2 | - | - | מחרוזת הקסה | - | תווי |
| 1 | כן | - | מספר שלם | - | char עם סימן |
| 1 | לא | - | מספר שלם | - | char ללא סימן |
| 1 | לא | - | מספר שלם | - | char ללא סימן; מניב נקודת קוד במצב |
| 2 | כן | native | מספר שלם |
|
|
| 2 | לא | native | מספר שלם |
|
|
| 4 | כן | native | מספר שלם |
|
|
| 4 | לא | native | מספר שלם |
|
|
| native | כן | native | מספר שלם |
|
|
| native | לא | native | מספר שלם |
|
|
| 8 | כן | native | מספר שלם |
| דורש Perl עם מספרים שלמים 64־ביט |
| 8 | לא | native | מספר שלם |
| דורש Perl עם מספרים שלמים 64־ביט |
| 2 | לא | big | מספר שלם |
| סדר רשת; |
| 4 | לא | big | מספר שלם |
| סדר רשת; |
| 2 | לא | little | מספר שלם |
| סדר ״VAX״; |
| 4 | לא | little | מספר שלם |
| סדר ״VAX״; |
| גודל IV | כן | native | מספר שלם |
|
|
| גודל UV | לא | native | מספר שלם |
|
|
| 4 | - | native | מספר |
| דיוק יחיד IEEE 754 |
| 8 | - | native | מספר |
| דיוק כפול IEEE 754 |
| גודל NV | - | native | מספר |
| מספר נקודה צפה פנים־Perl |
| משתנה | - | native | מספר |
| double ארוך |
| גודל ptr | - | native | מחרוזת |
| מבצע dereference למצביע למחרוזת המסתיימת ב־NUL |
| גודל ptr | - | native | מחרוזת |
| מבצע dereference למצביע; מונה = בתים לקריאה |
| משתנה | - | - | מחרוזת | - | בתים מפוענחי uudecode |
| משתנה | - | - | מספר שלם | - | מספר נקודת קוד של Unicode |
| משתנה | לא | - | מספר שלם | - | מספר שלם דחוס־BER |
| 1 | - | - | (אין) |
| דילוג בית אחד קדימה; |
| −1 | - | - | (אין) |
| חזרה בית אחד אחורה; |
| מוחלט | - | - | (אין) |
| קפיצה למיקום N בתוך הקבוצה הפנימית ביותר |
| - | - | - | מספר שלם |
| החזרת המיקום הנוכחי (יחסית להתחלת הקבוצה / המחרוזת) |
| - | - | - | - |
| קבוצה: מונה חזרות ו־endianness מתפשטים פנימה |
| - | - | - | - | - | ראו ״מטענים בעלי קידומת אורך״ להלן |
| משתנה | - | - | מספר שלם | - | קידומת. checksum בן N־ביט של ערכי ההוראה הבאה |
למתאמים אותה משמעות כמו ב־pack: ! בוחר גדלים native, סמנטיקת יישור, סימן עבור n / N / v / V, או היסטי בתים עבור @ / .; < / > כופים endianness.
הבדלים מ־pack#
aאינו מסיר דבר (מחזיר בתים גולמיים);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־ביט של הערכים שההוראה הייתה מפיקה אחרת.%32W*הוא checksum שלsumב־System V.%32b*סופר ביטים מודלקים..מחזיר את מיקום הבית הנוכחי במקום למלא באפסים עד אליו. שימושי לאחר ניווטx/Xכדי לדעת היכן נמצאים.pו־Pמבצעים dereference למצביעים שנקראו מהקלט - כמעט תמיד לא־בטוח אלא אם יודעים שהקלט הופק על־ידיpack "p"/pack "P"באותו תהליך.התנהגות under-run / over-run: אם התבנית מבקשת יותר נתונים ממה ש־
EXPRמכיל, התוצאה אינה מוגדרת היטב (עלולה להניב מחרוזות ריקות, אפסים, מונה חזרות מופחת, או חריגה). אםEXPRארוך יותר ממה שהתבנית צורכת, בתים מסיימים נדחים בשקט.
דוגמאות#
פרסור של כותר פרוטוקול בינארי מינימלי - גרסה 16־ביט, אורך 32־ביט, ואז מטען באורך משתנה, הכול בסדר בתי רשת:
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"
חילוץ checksum בסגנון System V עם הקידומת % - הסכום 32־ביט של כל בית, ממוסך ל־16 ביטים:
my $checksum = do {
local $/; # slurp
unpack "%32W*", readline $fh;
} % 65535;
ספירת ביטים מודלקים בווקטור ביטים - %32b* קורא את כל המסכה כביטים ומחזיר את הסכום שלהם:
my $setbits = unpack "%32b*", $selectmask;
קריאת רצף של מספרים שלמים 32־ביט little-endian מבופר גולמי:
my @ints = unpack "V*", $buf;
שימוש ב־x לדילוג על בתי מילוי, X לחזרה אחורה לאחר הצצה:
# 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
*חמדן, לא מציין־מקום.A*צורך את כל הבתים הנותרים כמחרוזת אחת; אין חזרה לאחור. הוראת*חייבת להיות האחרונה ברצף שלה, אחרת דבר אחריה אינו רץ.תבניות אינן ביטויים רגולריים. רווח לבן נדחה, אך אין חלופה, אין
|, אין lookahead. אם צורת הנתונים תלויה בשדות קודמים, יש לעשות unpack בשלבים: לפענח כותר, ואז לקרוא ל־unpackשוב על המטען תוך שימוש בתבנית שנגזרה ממה שזה עתה נקרא.סמנטיקת בית מול תו.
unpackרץ במצב בתים כברירת מחדל על מחרוזת בתים, ובמצב תווים על מחרוזת עם דגל UTF-8 מודלק.C0כופה מצב בתים מהנקודה ההיא;U0כופה מצב UTF-8. ערבוב מחרוזת מסומנת־UTF-8 עם הוראות מספריות כגוןNקורא נקודות קוד, לא בתים - בדרך כלל לא מה שרוצים. יש לקרוא ל־utf8::encodeראשון, או לפעול על נתונים ברמת בית.Xשמעבר לתחילת המחרוזת הוא קטלני.p/Pעל קלט שרירותי הוא התנהגות לא מוגדרת. אין להשתמש בהם אף פעם על נתונים שלא ארזתם בעצמכם באותו תהליך.ללא ארגומנט
EXPR:unpack TEMPLATEקורא מ־$_. שימושי בתוך לולאותwhile (<$fh>) { ... }על רשומות ברוחב קבוע.
הבדלים מהמעלה־הזרם#
תאימות מלאה עם Perl 5.42 מהמעלה־הזרם.
ראו גם#
pack- הפעולה ההפוכה; אותה שפת תבניותsubstr- חילוץ פרוסה קבועה יחידה; פשוט יותר עבור שדה אחד, איטי יותר עבור רביםsprintf- מסלול הלוך־ושוב בין בינארי לקריא־לאדםread- קריאת בתים גולמיים ממטפל קובץ לבופר עבורunpackvec- גישה מאונדקסת לווקטור ביטים ללא תבניתהדרכת pack/unpack - סיור מבוסס־משימות עם דוגמאות פרוטוקול ופורמט קובץ מעובדות