Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inline regex replacement in perl

Is there a way to replace text with a regex inline, rather than taking the text from a variable and storing it in a variable?

I'm a perl beginner. I often find myself writing

my $foo = $bar;
$foo =~ s/regex/replacement/;
doStuff($foo)

where I'd really like to write

doStuff($bar->replace(s/regex/replacement/));

or the like, rather than using a temporary variable and three lines.

Is there a way to do this? Obviously when the regex is sufficiently complicated it makes sense to split it out so it can be better explained, but when it's just s/\s//g it feels wrong to clutter the code with additional variables.

like image 409
Charles Avatar asked Jul 25 '10 20:07

Charles


2 Answers

You really can't do what you want because the substitution function returns either a 1 if it worked or an empty string if it didn't work. That means if you did this:

doStuff($foo =~ s/regex/replacement/);

The doStuff function would be using either 1 or an empty string as a parameter. There is no reason why the substitution function couldn't return the resultant string instead of just a 1 if it worked. However, it was a design decision from the earliest days of Perl. Otherwise, what would happen with this?

$foo = "widget";
if ($foo =~ s/red/blue/) {
    print "We only sell blue stuff and not red stuff!\n";
}

The resulting string is still widget, but the substitution actually failed. However, if the substitution returned the resulting string and not an empty string, the if would still be true.

Then, consider this case:

$bar = "FOO!";
if ($bar =~ s/FOO!//) {
   print "Fixed up \'\$bar\'!\n";
}

$bar is now an empty string. If the substitution returned the result, it would return an empty string. Yet, the substitution actually succeeded and I want to my if to be true.

In most languages, the substitution function returns the resulting string, and you'd have to do something like this:

if ($bar != replace("$bar", "/FOO!//")) {
   print "Fixed up \'\$bar''!\n";
}

So, because of a Perl design decision (basically to better mimic awk syntax), there's no easy way to do what you want. However you could have done this:

($foo = $bar) =~ s/regex/replacement/;
doStuff($foo);

That would do an in place setting of $foo without first assigning it the value of $bar. $bar would remain unchanged.

like image 59
David W. Avatar answered Oct 19 '22 09:10

David W.


Starting from perl 5.14 you can use Non-destructive substitution to achieve desired behavior.

Use /r modifier to do so:

doStuff($bar=~s/regex/replacement/r);
like image 38
alexeypetrenko Avatar answered Oct 19 '22 09:10

alexeypetrenko