מחרוזות, ביטים וחצאי־בתים#
בסוף הפרק הזה תוכלו לארוז ולפענח מחרוזות ברוחב קבוע, מחרוזות מסוימות־NUL בסגנון C, מחרוזות ביטים ומחרוזות hex - שלוש משפחות ההוראות מעין־טקסטואליות.
פורמטים בינאריים נושאים נתוני מחרוזת במגוון טעמים מובחנים: בתים גולמיים, טקסט מרופד־רווחים, מחרוזות C מסוימות־NUL, שדות ביטים, מספרים מקודדי־hex. ל־pack יש הוראה לכל אחד.
שלוש הוראות המחרוזת: a / A / Z#
כל השלוש אורזות בדיוק ערך אחד לרוחב קבוע. הן נבדלות במה שהן מרפדות בו, ו - חשוב מאוד - במה ש־unpack מסיר חזרה:
אות | בית ריפוד | unpack מחזיר | שימוש טיפוסי |
|---|---|---|---|
|
| כל הבתים ללא שינוי | בינארי שרירותי |
|
| רווח גורר ו־NUL מוסרים | טקסט ASCII ברוחב קבוע |
|
| בתים עד ל־NUL הראשון | מסוים־NUL בסגנון C |
הרוחב הוא מונה החזרות, לא מונה ערכים:
pack "a4", "hi" # "hi\0\0"
pack "A4", "hi" # "hi "
pack "Z4", "hi" # "hi\0\0"
pack "a4", "abcdef" # "abcd" - truncated
pack "A*", "hello" # "hello" - whatever the value's length is
Z מבטיח NUL גורר - עם הסתייגות#
Z תמיד שומר מקום ל־NUL מסיים אחד לפחות:
pack "Z*", "hello" # "hello\0" - a free NUL appended
pack "Z5", "hello" # "hell\0" - truncated to make room!
אם תוכנית C בצד השני מצפה ל־char[32] מסוים־אפס, השתמשו ב־Z32. הוא יארוז עד 31 בתים של נתונים בתוספת המסיים.
בחירה בין a ל־A לטקסט#
הנתונים הם ASCII, מרופדים ברווחים על הדיסק →
A.הנתונים הם בתים שרירותיים (עשויים להכיל רווחים או NULs כתוכן תקף) →
a.
המלכודת הקלאסית: אתם אורזים שם עם A20 ופורמט החוט משתמש בריפוד NUL. unpack "A20" מסיר גם רווחים וגם NULs, אז זה נראה בסדר - אך pack "A20", "bob" יבצע נסיעה חזור ל־"bob " מרופד ברווחים. אם המפרט אומר ריפוד NUL, השתמשו ב־a בצד ה־pack.
דוגמה מפותחת: רשומות טקסט ברוחב קבוע#
קובץ פנקס מסדר נתונים בעמודות:
0 1 2 3 4
0123456789012345678901234567890123456789012345678
2026-04-22 coffee at the station 3.50
2026-04-23 train to Brussels 42.00
עמודה 1-10 היא התאריך, 12-38 התיאור, 40-47 הסכום. הפערים הם רווחים בודדים (בית 11 ובית 39). unpack עם A10 x A27 x A* מקלף כל רשומה:
while (<$ledger>) {
chomp;
my ($date, $desc, $amount) = unpack "A10 x A27 x A*", $_;
print " $date | $desc | $amount\n";
}
x מדלג על בית אחד; A27 אוכל את עמודת התיאור ומסיר רווחים גוררים; A* אוכל בחמדנות את הבתים הנותרים כסכום. צד הפלט משתמש בשדות רחבים יותר כדי שרווחים ישרדו את הנסיעה חזור:
my $line = pack "A11 A28 A8 A*", $date, $desc,
sprintf("%.2f", $amt_left),
sprintf("%12.2f", $amt_right);
שימו לב לבית הנוסף בכל רוחב A - אותו בית בודד נוסף הוא פער העמודה. תקציב בתים עקבי לכל עמודה הוא מה שהופך רשומות ברוחב קבוע לבנות־טיפול בכלל.
מחרוזות ביטים: b ו־B#
מחרוזת ביטים היא מחרוזת של תווי "0" ו־"1" הנארזת לביטים בפועל. שתי הוראות, הנבדלות רק בכיוון שבו קוראים כל בית:
הוראה | סדר ביטים בתוך כל בית |
|---|---|
| LSB ראשון - ביט 0, 1, 2, 3, 4, 5, 6, 7 |
| MSB ראשון - ביט 7, 6, 5, 4, 3, 2, 1, 0 |
מונה החזרות הוא מספר הביטים, לא בתים:
pack "B8", "10001100" # "\x8c" - MSB first, bit 7 set, bit 3 & 2 set
pack "b8", "00110001" # "\x8c" - LSB first, same byte
B מתאים למוסכמה הרגילה ״משמאל־לימין הוא מגבוה־לנמוך״ שרואים ב־dumps בינאריים; b מתאים למוסכמה המשמשת חלק מ־hardware registers ול־built-in vec. השתמשו ב־B כאשר אתם כותבים החוצה מספר בינארי ״רגיל״, ב־b כאשר אתם משקפים data sheet שממספר את ביט 0 בצד ימין.
ספירת ביטים דלוקים#
אחד השימושים המפתיעים יותר של unpack: ספירת ביטים דלוקים במאגר בקריאה אחת. %32b* מפענח את הביטים ומבקש סכום 32-ביט, שהוא המונה:
my $n_bits = unpack "%32b*", $mask;
הקידומת %N היא ל־unpack בלבד - ראו את פרק המיקום לשימושים האחרים.
מחרוזות hex: h ו־H#
מחרוזות hex הן ייצוג הטקסט שרוב המפתחים קוראים - שתי ספרות hex לכל בית. שתי הוראות, הנבדלות בסדר החצאי־בתים:
הוראה | סדר חצאי־בתים |
|---|---|
| חצי־בית נמוך ראשון |
| חצי־בית גבוה ראשון |
H הוא ה־hex dump ה״רגיל״ - קריאה משמאל לימין, ספרה גבוהה ואז נמוכה:
pack "H*", "deadbeef" # "\xde\xad\xbe\xef"
unpack "H*", "\xde\xad\xbe\xef" # "deadbeef"
h הופך את חצאי־הבתים של כל בית - לעיתים רחוקות מה שאתם רוצים אלא אם מפרט אומר זאת במפורש. אם הנסיעה חזור שאתם מצפים לה אינה מה שאתם מקבלים, נסו את האות האחרת.
pack "h*", "ef" # "\xfe" (nybbles swapped)
pack "H*", "ef" # "\xef"
בחירה ביניהם#
יש לכם | פנו אל |
|---|---|
ASCII בעמודה ברוחב קבוע על הדיסק |
|
בתים שרירותיים בחריץ ברוחב קבוע |
|
מחרוזת מסוימת־NUL בסגנון C |
|
מספר בינארי כמחרוזת של |
|
זהה, עם סדר הביטים של מוסכמת register |
|
מחרוזת hex בסדר הקריאה הרגיל |
|
מחרוזת hex עם חצאי־בתים מוחלפים |
|
ביטים, חצאי־בתים, והוראות מחרוזת כולם חולקים כלל אחד: מונה החזרות מציין את הרוחב של הערך הבודד הנארז, לא את מספר הערכים. זו העובדה האחת לקחת הלאה.
הבא בתור: קבוצות () ומוני חזרות, הכלים להחלת תבנית של הוראות על רשימת ערכים באורך לא ידוע.