How do I perform a Perl substitution on a string while keeping the original?
Solution 1
This is the idiom I've always used to get a modified copy of a string without changing the original:
(my $newstring = $oldstring) =~ s/foo/bar/g;
In perl 5.14.0 or later, you can use the new /r
non-destructive substitution modifier:
my $newstring = $oldstring =~ s/foo/bar/gr;
NOTE:
The above solutions work without g
too. They also work with any other modifiers.
SEE ALSO:
perldoc perlrequick
: Perl regular expressions quick start
Solution 2
The statement:
(my $newstring = $oldstring) =~ s/foo/bar/g;
Which is equivalent to:
my $newstring = $oldstring;
$newstring =~ s/foo/bar/g;
Alternatively, as of Perl 5.13.2 you can use /r
to do a non destructive substitution:
use 5.013;
#...
my $newstring = $oldstring =~ s/foo/bar/gr;
Solution 3
Under use strict
, say:
(my $new = $original) =~ s/foo/bar/;
instead.
Solution 4
The one-liner solution is more useful as a shibboleth than good code; good Perl coders will know it and understand it, but it's much less transparent and readable than the two-line copy-and-modify couplet you're starting with.
In other words, a good way to do this is the way you're already doing it. Unnecessary concision at the cost of readability isn't a win.
Solution 5
Another pre-5.14 solution: http://www.perlmonks.org/?node_id=346719 (see japhy's post)
As his approach uses map
, it also works well for arrays, but requires cascading map
to produce a temporary array (otherwise the original would be modified):
my @orig = ('this', 'this sucks', 'what is this?');
my @list = map { s/this/that/; $_ } map { $_ } @orig;
# @orig unmodified
Related videos on Youtube
kaybenleroll
Software Developer in Ireland, who is fond of asking questions...
Updated on May 13, 2021Comments
-
kaybenleroll almost 3 years
In Perl, what is a good way to perform a replacement on a string using a regular expression and store the value in a different variable, without changing the original?
I usually just copy the string to a new variable then bind it to the
s///
regex that does the replacement on the new string, but I was wondering if there is a better way to do this?$newstring = $oldstring; $newstring =~ s/foo/bar/g;
-
ysth over 15 yearsWhether or not under use strict. Minimal scoping of variables++
-
ysth over 15 yearsAh, but the one line version isn't subject to the error in the question of unintentionally modifying the wrong string.
-
Josh Millard over 15 yearsThe one line version, <i>if correctly executed</i>, isn't subject, true. But that's a separate issue.
-
brian d foy over 15 yearsYou might think it's unnecessary concision, but having to type a variable name twice to use it once is twice the number of points of failure. It's perfectly readable to people who know the language, and it's even in our <i>Learning Perl</i> course.
-
glenn jackman over 14 yearsIf you
use warnings;
instead of-w
, you gain greater control: for instance, if you want to temporarily turn off warnings in a block of code. -
Benoit about 10 yearsI was wondering if something like
my $new = $_ for $old =~ s/foo/bar;
would work? -
mareoraft over 9 yearsDid you forget the
g
in your top regex? -
Teepeemm about 8 yearsHow is this different from the original? (And I think you want
=~ s
.) -
ikegami about 7 years@Benoit, I believe you mean
s/foo/bar/ for my $newstring = $oldstring;
It works, but it's far weirder. -
Pascal over 6 yearsClbuttic mistake. The actual output of that code is
newword donotnewword newword donotnewword newword donotnewword
-
Jon over 5 yearsSee... if JoGotta had used the traditional and familiar
foo
andbar
, his answer would have been accurate. Proving, once again, customs exist for a reason and lessons are only learned the hard way. ;) -
Peter Mortensen about 3 years
-
Peter Mortensen about 3 yearsWho? Wikipedia has part of the answer. Incl.: "The etymology of foobar could be derived from the military slang from the World War II era FUBAR, which was bowdlerised to foobar. The word foo on its own was used earlier. ... The first known use of the terms in print in a programming context appears in a 1965 edition of MIT's Tech Engineering News."