views:

1818

answers:

5

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;
$oldstring =~ s/foo/bar/g;
+27  A: 

This is the idiom I've always used to get a modified copy of a string without changing the original:

($new = $original) =~ s/foo/bar/;
John Siracusa
under "use strict" write this:(my $new = $original) =~ s/foo/bar/;
szabgab
Whether or not under use strict. Minimal scoping of variables++
ysth
+8  A: 

Just a word of caution, John's answer correctly answers the question, but

($new = $original) =~ s/foo/bar/;

Is equivalent to

$newstring = $oldstring;
$newstring =~ s/foo/bar/g; #Modify $newstring instead of $oldstring

Which is I think what you meant in the first place. Probably better edit the question and correct your sample code.

Pat
A: 

If you write Perl with use strict;, then you'll find that the one line syntax isn't valid, even when declared.

With:
my ($newstring = $oldstring) =~ s/foo/bar/;

You get:
Can't declare scalar assignment in "my" at script.pl line 7, near ") =~" Execution of script.pl aborted due to compilation errors.

Instead, the syntax that you have been using, while a line longer, is the syntactically correct way to do it with use strict;. For me, using use strict; is just a habit now. I do it automatically. Everyone should.

#!/usr/bin/env perl -wT

use strict;

my $oldstring = "foo one foo two foo three";
my $newstring = $oldstring;
$newstring =~ s/foo/bar/g;

print "$oldstring","\n";
print "$newstring","\n";
Tim Kennedy
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.
glenn jackman
+7  A: 

Under use strict, say

(my $new = $original) =~ s/foo/bar/;

instead.

Sam Kington
+3  A: 

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.

Josh Millard
Ah, but the one line version isn't subject to the error in the question of unintentionally modifying the wrong string.
ysth
The one line version, <i>if correctly executed</i>, isn't subject, true. But that's a separate issue.
Josh Millard
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.
brian d foy