החלפה#

s/// הוא אופרטור החיפוש־וההחלפה. צורתו הכללית היא

$target =~ s/pattern/replacement/modifiers;

הוא מוצא את המיקום הראשון שבו תבנית מתאימה במטרה, מחליף את ההתאמה בהחלפה, ומחזיר את מספר ההחלפות שבוצעו. עם /g, הוא עושה זאת עבור כל התאמה שאינה חופפת.

my $x = "Time to feed the cat!";
$x =~ s/cat/hacker/;          # $x is now "Time to feed the hacker!"

אם התבנית אינה מתאימה, המטרה נותרת ללא שינוי ו־s/// מחזיר ערך שקר.

פעולה על $_#

כמו m//, s/// מוגדר כברירת מחדל ל־$_ כאשר לא ניתן =~:

for (@lines) {
    s/\s+$//;       # trim trailing whitespace from each line
}

ספירת החלפות#

ערך ההחזרה של s/// בהקשר סקלרי הוא מספר ההחלפות:

my $count = ($text =~ s/\btodo\b/done/gi);
print "cleared $count todos\n";

בהקשר בוליאני, אפס פירושו אין התאמה.

מחרוזת ההחלפה#

ההחלפה היא מחרוזת במרכאות כפולות, כך שמשתנים ורצפי בריחה משובצים בה:

my $suffix = ".bak";
$file =~ s/$/$suffix/;    # append .bak to the name

$x =~ s/\t/    /g;        # each tab becomes four spaces

בתוך ההחלפה, $1, $2, $&, $+ וחבריהם מתייחסים למה שההתאמה הנוכחית זה עתה לכדה:

my $y = "'quoted words'";
$y =~ s/^'(.*)'$/$1/;     # strip surrounding single quotes
# $y is now "quoted words"

לכידות בשם פועלות באותו אופן באמצעות $+{name}:

"2026-04-23" =~ s/(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})/$+{d}\/$+{m}\/$+{y}/;
# result: "23/04/2026"

מילוט בהחלפה#

ההחלפה מפורשת כמחרוזת במרכאות כפולות, ולכן כללי המרכאות הכפולות חלים עליה, באופן עצמאי מהתבנית. תווים מטא כמו *, +, ?, $ שומרים על משמעותם במרכאות כפולות — רק $ ו־@ מפעילים שיבוץ:

$x =~ s/(\w+)/[$1]/g;     # wrap every word in brackets
$x =~ s/\$/USD/g;         # replace literal '$' with 'USD'

Backslash escape sequences in the replacement follow the double-quote rules — \t, \n, \x{…} all work. The special case-modification escapes \l, \u, \L, \U, \E, \Q apply in the replacement too:

$x =~ s/(\w+)/\u$1/g;     # capitalise the first letter of each word
$x =~ s/(\w+)/\U$1\E/g;   # uppercase whole word

אזהרה: \1 מול $1 בהחלפה#

ניב שעבר תהליך התאזרחות ארוך: כתיבת \1, \2, … בהחלפה במשמעות ״הלכידה הראשונה״, ״הלכידה השנייה״:

$pattern =~ s/(\W)/\\\1/g;     # works, but is a trap

Perl מקבלת \1 עד \9 בהחלפה של s/// לצורכי תאימות היסטורית עם sed. יש להשתמש ב־$1 עד $9 במקום. הסיבה היא שההחלפה היא מחרוזת במרכאות כפולות, שבה \1 בדרך כלל פירושו תו control-A. כלל המקרה המיוחד של אופרטור ההחלפה מאלתר את הפירוש של המרכאות הכפולות כך שיהיה ״לכידה ראשונה״, אך הקצוות חדים.

באופן ספציפי: שילוב של \1 עם /e מחזיר את המשמעות של מרכאות כפולות. תחת /e, ההחלפה היא קוד Perl; בקוד Perl, "\1" הוא control-A:

s/(\d+)/ \1 + 1 /eg;   # warning: \1 better written as $1

קצה חד שני: \1 ואחריו תווי ספרות הוא דו־משמעי. \1000 יכול להתפרש כ״לכידה ראשונה, ואז 000 מילולי״, או כ״0x40 אוקטלי (@) — ולא ניתן ליישב את הדו־משמעות באמצעות כתיבת \{1}000״:

s/(\d+)/\1000/;     # ambiguous, best avoided
s/(\d+)/${1}000/;   # unambiguous

הכלל לקוד חדש: תמיד יש להשתמש ב־$1 בהחלפה, לעולם לא ב־\1. הצורה \1 שרדה כירושה היסטורית, ואינה מומלצת.

/g — החלפת הכל#

ללא /g, s/// מחליף רק את ההתאמה הראשונה. עם /g, הוא מחליף כל התאמה שאינה חופפת משמאל לימין:

my $x = "I batted 4 for 4";
$x =~ s/4/four/;         # "I batted four for 4"
$x = "I batted 4 for 4";
$x =~ s/4/four/g;        # "I batted four for four"

/g בהחלפה אינו קשור ל־/g בהתאמה. כאן הוא פשוט אומר ״עשה זאת שוב ושוב עד שהתבנית מפסיקה להתאים״.

התאמות אורך אפס ו־s///g#

תבנית היכולה להתאים את המחרוזת הריקה מציבה בעיה תחת /g: כל מיקום היה מתאים שוב לעולם. Perl שוברת את הלולאה הזו עם כלל ספציפי: לאחר התאמת אורך אפס, הניסיון הבא באותו מיקום אסור להיות גם הוא באורך אפס. המנוע לוקח במקום זאת את ההתאמה הטובה ביותר השנייה.

ההדגמה הנקייה ביותר:

$_ = 'bar';
s/\w??/<$&>/g;
# Result: <><b><><a><><r><>

ה־\w?? הלא־חמדן מעדיף את ההתאמה הריקה. לאחר ייצור אחת, האיטרציה הבאה אסורה להיות גם היא באורך אפס, לכן המנוע לוקח את ההתאמה הטובה ביותר השנייה — תו \w בודד. ואז עוד התאמה ריקה, ואז עוד תו, וכן הלאה, לסירוגין עד שהמחרוזת נצרכת.

התבנית: התאמות אורך אפס מתחלפות עם התאמות של תו אחד, וההחלפה אינה נכנסת ללולאה אינסופית.

מסקנה שימושית: s/(\d{3})/$1,/g אינו מכניס פסיק אחרי כל קבוצה של שלוש ספרות באופן נכון — הוא מכניס אחרי השלוש הראשונות משמאל, ואז השלוש הבאות, ללא קשר למיקום שבו רציתם את הפסיקים. כדי להכניס מפרידי אלפים, יש להתאים מימין או להשתמש ב־1 while:

my $n = "1234567";
1 while $n =~ s/^(\d+)(\d{3})/$1,$2/;
# n is now "1,234,567"

ה־1 while חוזר עד שההחלפה מחזירה שקר (אין יותר התאמות), וזה בדיוק מה שרוצים עבור ״כל מיקום, לאחר התייצבות״.

/e — הערכת ההחלפה#

תחת /e, ההחלפה היא קוד Perl, ולא מחרוזת. הקוד רץ עבור כל התאמה וערך ההחזרה שלו מחליף את ההתאמה.

my $x = "numbers: 1 2 3 4";
$x =~ s/(\d+)/$1 * 2/ge;      # "numbers: 2 4 6 8"

משתני ההתאמה $1, $2, … גלויים בתוך בלוק הקוד.

שימושים מעשיים:

# Uppercase the first letter of every sentence.
$text =~ s/(^|\.\s+)(\w)/$1\U$2/g;

# Hex-encode non-ASCII bytes.
$bytes =~ s/([\x80-\xff])/sprintf "\\x%02x", ord $1/ge;

# Apply a lookup table.
my %subst = (red => 0xff0000, green => 0x00ff00, blue => 0x0000ff);
$css =~ s/\b(red|green|blue)\b/sprintf "#%06x", $subst{$1}/ge;

/ee — הערכה כפולה#

/ee מעריך פעמיים — תחילה כקוד, ואז התוצאה עצמה מוערכת כ־Perl. המקרה לשימוש הוא חיפוש דינמי של משתנה לפי שם:

our $greeting = "hello";
my $s = "greeting";
$s =~ s/(\w+)/"\$$1"/ee;         # first: '$greeting'; second: 'hello'
# $s is now "hello"

ההחלפה היא ביטוי Perl — המרכאות הכפולות המפורשות גורמות לו להפיק את המחרוזת "$greeting". ה־e הראשון מעריך את הביטוי הזה למחרוזת $greeting. ה־e השני מתייחס למחרוזת הזו כ־Perl, מחפש את המשתנה $greeting ומפיק hello. מיקום ההתאמה מוחלף בערך hello.

המקרה לשימוש מצומצם וההשלכות האבטחתיות משמעותיות: כל קלט המגיע להחלפת /ee מורץ למעשה כ־Perl. יש להתייחס ל־/ee כמו אל eval — לעולם לא על נתונים שסופקו על ידי משתמש.

/r — החלפה לא־הרסנית#

/r מחזיר את המחרוזת החדשה במקום לשנות את המטרה. המטרה אינה נוגעת:

my $orig = "I like dogs";
my $new = $orig =~ s/dogs/cats/r;
# $orig is still "I like dogs"
# $new is "I like cats"

אם התבנית אינה מתאימה, /r מחזיר את המחרוזת המקורית ללא שינוי:

my $x = "I like dogs";
my $y = $x =~ s/elephants/cougars/r;
# $y eq "I like dogs"

הרווח הגדול הוא בשרשור:

my $slug = $title
    =~ s/[^\w\s-]//gr         # drop punctuation
    =~ s/\s+/-/gr             # collapse spaces to dash
    =~ s/--+/-/gr;            # collapse runs of dashes

כל חץ מחזיר מחרוזת חדשה, שאותה מקבל ה־s///r הבא.

\K בהחלפה#

\K (מכוסה בפירוט בפרק anchors and assertions) זורח בהחלפה. התבנית מתאימה קידומת שמבססת הקשר, ואז \K מוציא את הקידומת ממטרת ההחלפה:

# Without \K — the prefix has to be re-output:
$_ =~ s/(foo)bar/$1/g;

# With \K — the prefix is matched but not part of $&:
$_ =~ s/foo\Kbar//g;

שתיהן מחליפות foobar ב־foo. צורת ה־\K נקייה יותר: אין צורך בלכידה, ותבנית ההחלפה קצרה ומהירה יותר.

\K עובד באופן דומה בכל החלפה שבה קידומת קבועה צריכה להתאים אך לא להיות מוחלפת. זהו התאום בצד ההחלפה של הצצה לאחור.

החלפה ו־pos()#

s///g מוצלח מקדם את pos($string) מעבר לכל התאמה. התאמת אורך אפס מקדמת את pos באחד כדי לשבור את הלולאה. לאחר ההחלפה, pos מאופס.

אינטראקציה עדינה: s///g לא יסרוק מחדש אזור שזה עתה הותאם. לאחר כל החלפה מוצלחת מיקום ההתאמה מתקדם מעבר לטקסט המותאם — אורך ההחלפה אינו משנה. לכן:

my $x = "aaa";
$x =~ s/a/AA/g;
# $x is "AAAAAA" — three a's, each replaced with AA
# It is NOT an infinite loop: pos() moves past each matched 'a',
# so the just-inserted 'A's are never re-scanned.

זה לעיתים מפתיע עבור החלפות שההחלפה שלהן מכילה תווים שהתבנית גם הייתה מתאימה. הכלל הוא ״התקדם מעבר לטקסט המותאם, לעולם אל תסרוק אותו מחדש״.

תוחמים חלופיים#

שני החצאים של s/// יכולים להשתמש בסוגריים מותאמים; אין צורך שהתוחמים יהיו זהים:

s{pattern}{replacement}g;
s<pattern><replacement>g;
s[pattern][replacement]g;
s(pattern)[replacement]g;    # legal, but avoid mixing for clarity

כל תו פיסוק שניתן להדפסה עובד בצורה של תו בודד:

s!/usr/local/!/opt/!g;
s#pattern#replacement#;

שימושי כאשר התבנית או ההחלפה מכילות /.

החלפה במרכאות בודדות#

s'pattern'replacement' מתייחס לשני החצאים כמרכאות בודדות — ללא שיבוץ משתנים, ללא רצפי בריחה עם לוכסן הפוך פרט ל־\' ול־\\:

s'@users'@admins'g;     # literal '@users' becomes literal '@admins'

נדרש לעיתים רחוקות; מוזכר כאן לשם השלמות.

שילוב עם /m, /s, /x#

מתאמי החלפה מתחברים עם מתאמי התאמה, כך שניתן לקבל את ארגז הכלים המלא:

# Trim each line.
$x =~ s/^\s+|\s+$//mg;

# Collapse blank lines.
$x =~ s/\n{2,}/\n\n/g;

# Replace C-style comments across newlines.
$src =~ s{/\*.*?\*/}{}gs;   # /s lets . cross newlines

עם /x התבנית קריאה, עם /s היא משתרעת על מעברי שורה, עם /g היא חוזרת.

דוגמה אמיתית#

הופכים בלוק של טקסט אנגלי ל־slug — אותיות קטנות, מקפים במקום רווחים, הסרת תווים שאינם אותיות, כיווץ וגזירה:

sub slug {
    my ($s) = @_;
    return lc($s)
        =~ s/[^\w\s-]//gr     # remove punctuation
        =~ s/\s+/-/gr          # spaces to hyphens
        =~ s/-+/-/gr           # collapse hyphens
        =~ s/^-|-$//gr;        # trim leading/trailing hyphens
}

print slug("Hello, World! -- Regex Tutorial");
# prints: hello-world-regex-tutorial

הניסוח של פרידל — ״כל דבר שאינו נדרש ייחשב תמיד כמוצלח״#

חלקי תבנית אופציונליים יצליחו תמיד אם הם יכולים להתאים לכלום. זה חל בתוך החלפה באותו תוקף כמו בהתאמה:

my $x = "no horizontal rule here";
$x =~ s/-*/<HR>/;
# Result: "<HR>no horizontal rule here"

התבנית -* מתאימה אפס או יותר מקפים — ואפס תמיד זמין, בתחילת המחרוזת. <HR> מוכנס במיקום 0. התבנית הצליחה לפי הגדרת המנוע; היא נכשלה לפי שלכם.

התיקון הוא לדרוש לפחות מקף אחד:

$x =~ s/-+/<HR>/;       # no match; $x unchanged

הסיסמה: תמיד יש לשקול מה יקרה אם אין התאמה. חלקים אופציונליים אינם חינם; הם תמיד מצליחים על ידי התאמה לכלום באיזשהו מקום.

דברים שנראים כמו החלפה אך אינם#

tr/// (נכתב גם y///) מבצע תעתיק תו־תו, לא החלפה של ביטוי רגולרי. הוא מקבל שתי רשימות של תווים; כל הופעה של התו ה־n ברשימה הראשונה הופכת לתו ה־n ברשימה השנייה. תכונות של ביטוי רגולרי אינן חלות:

my $x = "Hello";
$x =~ tr/A-Za-z/a-zA-Z/;     # swap case
(my $hex = $bytes) =~ tr/\x00-\xff//d;   # delete all bytes — pointless

tr/// מהיר מ־s/// עבור עבודה ברמת התו מכיוון שהוא אינו מנוע ביטויים רגולריים. ראו tr לסמנטיקה מלאה.

ראו גם#

  • s — הפניה לאופרטור ההחלפה.

  • tr — תעתיק תווים; אינו החלפה אך מבולבל איתה לעיתים קרובות.

  • quotemeta — מילוט מחרוזת לשיבוץ בטוח בתבנית.

  • פרק modifiers/g, /e, /r, /ee, וכיצד הם מתקשרים זה לזה.

  • פרק anchors and assertions\K עבור ״התאם קידומת זו אך אל תחליף אותה״.

  • פרק performance — סיום התאמת אורך אפס של s///g בפירוט.