Regular expressions and pattern matching

s///#

Search a string for a pattern and replace every match with a replacement.

s/// is Perl’s substitution operator. It finds text matching PATTERN in the target string, replaces each match with REPLACEMENT, and by default returns the number of substitutions made. With no explicit target (no =~ or !~), it operates on $_. The target must be a scalar lvalue — a variable, an array or hash element, or a substr / assignment producing one — unless the /r flag is used, which works on any value and returns the modified copy.

Synopsis#

s/PATTERN/REPLACEMENT/FLAGS
$str =~ s/PATTERN/REPLACEMENT/FLAGS
$str !~ s/PATTERN/REPLACEMENT/FLAGS
my $copy = $str =~ s/PATTERN/REPLACEMENT/r

What you get back#

By default, the count of substitutions performed as an integer: 0 when nothing matched (which is false in boolean context), a positive integer on success. The target scalar is modified in place.

With the /r flag, the semantics flip: the target is not modified, and the operator returns the (possibly changed) string. If nothing matched, /r still returns a copy of the original. The result of /r is always a plain string, even when the source is a tied variable or a blessed object with overloading.

!~ inverts the boolean sense of the return value: it yields true when nothing was substituted, false when at least one substitution happened. The target is still modified either way.

my $n = ($text =~ s/foo/bar/g);     # count of replacements
my $out = $text =~ s/foo/bar/r;     # copy-and-modify, $text untouched

Global state it touches#

  • $_ — the default target when no =~ or !~ is given. s/old/new/ with no binding reads and writes $_.

  • $&, [`$``](../perlvar), [`$’`](../perlvar), [`$1`](../perlvar) and friends — set by each successful match, the same way [`m//`](m) sets them. Inside `REPLACEMENT` they refer to the current match, not any earlier one.

  • pos — cleared on the target scalar by a successful non-/g substitution; under /g it advances with each match and can be inspected between iterations.

  • The last successful pattern — used when PATTERN evaluates to the empty string (s//new/ re-uses the last successful regex from this scope).

  • $/, $\ and output separators are not touched — s/// produces a string, it does not write one.

Flags#

The full set is msixpodualngcer. Match-side flags behave exactly as in m// and qr; see perlre for the match-side details. Replacement-specific flags:

  • e — evaluate REPLACEMENT as a block of Perl code. The block’s value is the replacement string. Equivalent to wrapping it in do { ... } and stringifying the result.

  • ee — evaluate as code, then eval the resulting string again. Equivalent to eval(do { REPLACEMENT }). Additional e modifiers add more eval layers.

  • r — non-destructive: leave the target unchanged and return the modified copy (or an unchanged copy on no match). Cannot be combined with a non-scalar-lvalue target restriction — any expression is a valid target under /r.

  • g — global: replace every non-overlapping match, not just the first.

  • c — accepted for syntactic symmetry with m// but has no behavioural effect on s///; triggers a warning under use warnings.

Match-side flags in one line: m (multiline ^/$), s (. matches newline), i (case-insensitive), x / xx (extended whitespace, comments), p (preserve match variables; obsolete since 5.20), o (compile pattern once), d / u / a / l (character-set semantics), n (non-capturing by default). See perlre.

Delimiters#

Any non-whitespace character may replace /. If the chosen delimiter is one of (, [, {, or <, the operator takes two bracketed groups and a delimiter between them is optional:

s(foo)(bar)
s{foo}{bar}
s<foo>/bar/
s[foo]{bar}g

Single-quote delimiters turn off interpolation in both PATTERN and REPLACEMENT (unless /e is in force, which always parses REPLACEMENT as code):

s'$name'$value';    # literal $name → literal $value, no interpolation

Backticks are ordinary delimiters; s`x`y` does not run a shell command.

When the delimiter is a character that is also an identifier character, a space after the s is required so the parser does not read it as part of the operator name.

Examples#

Basic in-place substitution on $_:

$_ = 'the quick brown fox';
s/quick/slow/;                  # $_ is now 'the slow brown fox'

Explicit target with =~:

my $path = '/usr/bin/perl';
$path =~ s|/usr/bin|/usr/local/bin|;
# $path is '/usr/local/bin/perl'

Global replacement, capturing the count:

my $text = 'one two two three two';
my $n = ($text =~ s/two/2/g);   # $text: 'one 2 2 three 2'; $n == 3

Non-destructive /r — leaves the source alone, returns the copy. Idiomatic in map:

my @clean = map { s/\s+\z//r } @lines;   # @lines untouched

Code evaluation with /e. The right-hand side is a Perl expression whose value becomes the replacement:

my $s = 'abc123xyz';
$s =~ s/\d+/$& * 2/e;           # $s is 'abc246xyz'

my %percent = (n => "\n", t => "\t");
$s =~ s/%(.)/$percent{$1} || $&/ge;     # expand %-escapes

Chained /r — pure-functional transforms with no intermediate variable:

my $out = $text =~ s/foo/bar/r
                =~ s/baz/qux/r;

Capture groups and backreferences in the replacement — note the $1 form, not \1:

# swap the first two whitespace-separated fields
s/(\S+)\s+(\S+)/$2 $1/;

The 1 while idiom for substitutions that create new matches:

# insert commas into an integer from the right
my $n = '1234567890';
1 while $n =~ s/(\d)(\d\d\d)(?!\d)/$1,$2/;
# $n is '1,234,567,890'

Edge cases#

  • Target must be a scalar lvalue (unless /r): a variable, element, or substr lvalue. s/x/y/ against a string literal or the result of a function call is a compile-time error. Under /r any expression is fair game since nothing is modified.

  • Empty pattern re-uses the last successful match. s//new/ substitutes against whatever PATTERN most recently matched in the enclosing scope. Convenient inside while (m/.../g) { s//x/ }, surprising when unrelated code has run in between.

  • Interpolation happens at runtime. s/$foo/$bar/ recompiles the pattern every call if $foo changes. Use /o to compile once and freeze the captured value — or precompile with qr, which is the modern alternative.

  • /e parses the replacement at compile time even though it runs at match time. Syntax errors surface when the script is loaded, not when the substitution fires. Each extra e wraps one more eval around the value.

  • /g with an empty match advances by one character to avoid an infinite loop: s/\b/-/g inserts between every token, it does not hang at the first position.

  • !~ flips the return, not the work. $x !~ s/A/a/g still modifies $x; it just returns true when no A was found.

  • Delimiter matching for brackets uses the mirrored closer: s{pat}{rep}, s<pat><rep>. A delimiter other than a bracket must appear three times total: s/pat/rep/.

  • /c is a no-op on s///. Accepted for parser symmetry with m//; using it produces a warning under use warnings and nothing more.

  • Assignment-as-target idiom. ($copy = $src) =~ s/x/y/g populates $copy with the modified value and leaves $src alone. Modern code prefers my $copy = $src =~ s/x/y/gr.

  • Tied or overloaded targets. Without /r, STORE is invoked after the substitution to write the new value back; the fetched value is copied into a plain buffer before the pattern is applied. With /r the result is always a plain string — tie / overloading is not preserved in the return.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • m// — the matching operator; shares match-side flag semantics and return-vs-context rules

  • tr/// — character-by-character transliteration; much faster when the job is literal character translation, not a regex

  • qr// — precompile a pattern once and interpolate it into many s/// or m// calls; the modern alternative to /o

  • split — when the goal is to break a string on a pattern rather than replace matches, reach for split instead

  • perlre — the full pattern-language reference; every match-side flag on s/// is defined there

  • $& — the matched text, available inside the REPLACEMENT of every s///