substr#
לחלץ, להחליף, או ליצור alias של פלח רציף של מחרוזת.
substr בוחר רצף של תווים מ־EXPR החל מ־OFFSET ושמשתרע על LENGTH תווים, ומחזיר את הפלח הזה. אותה קריאה יכולה גם לשנות את המחרוזת המקורית בשלוש דרכים נבדלות: כ־lvalue משמאל ל־=, דרך צורת REPLACEMENT של ארבעה ארגומנטים, או דרך lvalue עם alias שמאוחסן במשתנה שממשיך לעקוב אחר הפלח דרך כתיבות עוקבות. תו אפס הוא התו הראשון. 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"
השמה מעבר לסוף הנוכחי של המחרוזת מותרת, עד מיקום אחד מעבר לסוף (append-at-end). יותר מזה וההשמה מעלה חריגה.
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"
זה משקף את מבנה ה־extract-and-replace של splice על מערכים.
הטריק של lvalue עם alias#
הסקלר שצורת שלושת הארגומנטים מחזירה אינו עותק של התווים - הוא כדור קסם שזוכר לאיזה אזור של המחרוזת המקורית הוא מתייחס. אחסון ה־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 שלילי, ה־alias עוקב אחר סוף המחרוזת:
my $x = '1234';
for (substr($x, -3, 2)) {
$_ = 'a'; print $x, "\n"; # 1a4
$x = 'abcdefg';
print $_, "\n"; # f
}
זה שימושי כאשר משכתבים שוב ושוב את אותו חריץ של מאגר (שדות כותרת ברשומה בעלת פריסה קבועה, למשל) - אך זה גם מקור קלאסי להפתעות. עדיף את צורת ארבעת הארגומנטים אלא אם רוצים במפורש את ה־aliasing.
דוגמאות#
לחלץ שדה קבוע מרשומה:
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 ...
}
לשכתב את הבית האחרון של מאגר שוב ושוב דרך lvalue עם alias:
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פועל בתווים, לא בבתים. במחרוזת עם דגל UTF-8 מופעל, מיקומים סופרים נקודות קוד; במחרוזת בתים, מיקומים סופרים בתים. ערבוב השניים על־ידי התייחסות למחרוזת מפוענחת כמאגר בתים מייצר offsets שגויים - יש לפענח קודם, ואז לאנדקס.סקלרים tied או מאגיים:
substrכ־lvalue מכבד קסם בזמןSTOREעל היעד, כך שמשתנים tied רואים את המחרוזת השלמה ששונתה, לא את הפלח.lvalue עם alias שנשמר מעבר לאורך החיים של היעד שלו: אם המשתנה המקורי יוצא מהתחום בעוד ה־alias עדיין בחיים, כתיבות מאוחרות יותר דרך ה־alias פועלות על מחרוזת ששוחררה; יש לשמור את אורך החיים של ה־alias בתוך זה של היעד.
פינה לפני־5.10: לכתיבות חוזרות דרך lvalue יחיד הייתה התנהגות לא־מוגדרת ב־perls ישנים יותר, כמו גם ל־offsets שליליים לפני 5.16. Perl מודרני (ו־pperl) פועלים לפי הסמנטיקה המתועדת בעמוד זה.
הבדלים מ־upstream#
תואם מלא ל־upstream Perl 5.42.
ראו גם#
index- למצוא את המיקום של תת־מחרוזת, להזין ל־substrכ־OFFSETrindex- אותו דבר, חיפוש מימיןlength- הגבול העליון על כלOFFSETאוLENGTHבעל משמעות שמעבירים ל־substrsplice- האנלוג ברמת המערך של צורת ההחלפה של ארבעת הארגומנטיםpack/unpack- עבור רשומות בעלות פריסה קבועה שבהן שדות רבים נקראים או נכתבים מחדש בזריקה אחת, עדיפים על שרשרת קריאותsubstrtr///- החלפה ברמת תווים בכמויות שאינה זקוקה לאינדקסים מיקומיים