How do I perform a Perl substitution on a string while keeping the original?

218,974

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
Share:
218,974

Related videos on Youtube

kaybenleroll
Author by

kaybenleroll

Software Developer in Ireland, who is fond of asking questions...

Updated on May 13, 2021

Comments

  • kaybenleroll
    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
    ysth over 15 years
    Whether or not under use strict. Minimal scoping of variables++
  • ysth
    ysth over 15 years
    Ah, but the one line version isn't subject to the error in the question of unintentionally modifying the wrong string.
  • Josh Millard
    Josh Millard over 15 years
    The one line version, <i>if correctly executed</i>, isn't subject, true. But that's a separate issue.
  • brian d foy
    brian d foy over 15 years
    You 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
    glenn jackman over 14 years
    If 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
    Benoit about 10 years
    I was wondering if something like my $new = $_ for $old =~ s/foo/bar; would work?
  • mareoraft
    mareoraft over 9 years
    Did you forget the g in your top regex?
  • Teepeemm
    Teepeemm about 8 years
    How is this different from the original? (And I think you want =~ s.)
  • ikegami
    ikegami about 7 years
    @Benoit, I believe you mean s/foo/bar/ for my $newstring = $oldstring; It works, but it's far weirder.
  • Pascal
    Pascal over 6 years
    Clbuttic mistake. The actual output of that code is newword donotnewword newword donotnewword newword donotnewword
  • Jon
    Jon over 5 years
    See... if JoGotta had used the traditional and familiar foo and bar, his answer would have been accurate. Proving, once again, customs exist for a reason and lessons are only learned the hard way. ;)
  • Peter Mortensen
    Peter Mortensen about 3 years
  • Peter Mortensen
    Peter Mortensen about 3 years
    Who? 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."