I need to pass a regex substitution as a variable:
sub proc {
my $pattern = shift;
my $txt = \"foo baz\";
$txt =~ $pattern;
}
my $pattern = \'s
I have an extremely simple script for mass file renaming that employs this trick :
#!/opt/local/bin/perl
sub oops { die "Usage : sednames s/old/new [files ..]\n"; }
oops if ($#ARGV < 0);
$regex = eval 'sub { $_ = $_[0]; ' . shift(@ARGV) . '; return $_; }';
sub regex_rename { foreach (<$_[0]>) {
rename("$_", &$regex($_));
} }
if ($#ARGV < 0) { regex_rename("*"); }
else { regex_rename(@ARGV); }
Any perl command that modifies $_
like s/old/new
could be employed to modify the files.
I decided upon using eval
so that the regular expression only needed to be compiled once. There is some wonkiness with eval
and $_
that prevented me from using simply :
eval 'sub { ' . shift(@ARGV) . ' }';
although this &$regex
certainly does modify $_
; requiring the "$_"
to evaluate $_
before calling rename
. Yes, eval
is quite fragile, like everyone else said.
You're right - you were very close:
eval('$txt =~ ' . "$pattern;");
I found a probably better way to do it:
sub proc {
my ($pattern, $replacement) = @_;
my $txt = "foo baz";
$txt =~ s/$pattern/$replacement/g; # This substitution is global.
}
my $pattern = qr/foo/; # qr means the regex is pre-compiled.
my $replacement = 'bar';
proc($pattern, $replacement);
If the flags of the substitution have to be variable, you can use this:
sub proc {
my ($pattern, $replacement, $flags) = @_;
my $txt = "foo baz";
eval('$txt =~ s/$pattern/$replacement/' . $flags);
}
proc(qr/foo/, 'bar', 'g');
Please note that you don't need to escape /
in the replacement string.