问题
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.
回答1:
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);
回答2:
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.
回答3:
use Algorithm::Loops "Filter";
# leaves $foo unchanged
doStuff( Filter { s/this/that/ } $foo );
回答4:
You can use a do { }
block to avoid creating a temporary variable in the current scope:
doStuff( do {(my $foo = $bar) =~ s/regex/replacement/; $foo} );
回答5:
Is this what you want?:
my $foo = 'Replace this with that';
(my $bar = $foo) =~ s/this/that/;
print "Foo: $foo\nBar: $bar\n";
Prints:
Foo: Replace this with that
Bar: Replace that with that
回答6:
There is yet another way: Write your own function:
sub replace (
my $variable = shift;
my $substring = shift;
eval "\$variable =~ s${substring};";
return $variable
}
doStuff(replace($foo, "/regex/replace/"));
This wouldn't be worth it for a single call, and it would probably just make your code more confusing in that case. However, if you're doing this a dozen or so times, it might make more sense to write your own function to do this.
来源:https://stackoverflow.com/questions/3330882/inline-regex-replacement-in-perl