[英]How to use a variable as modifier in a substitution
Is there a way to use a variable as modifier in a substitution?有没有办法在替换中使用变量作为修饰符?
my $search = 'looking';
my $replace = '"find: $1 ="';
my $modifier = 'ee';
s/$search/$replace/$modifier;
I need to use an array of hashes to make bulk search-replace with different modifiers.我需要使用散列数组来使用不同的修饰符进行批量搜索替换。
You could use eval
, if you put on your safety goggles and your divide-by-zero suit.如果您戴上护目镜和除零套装,则可以使用
eval
。
Eg:例如:
use strict;
use warnings;
sub mk_re {
my ($search, $replace, $modifier) = @_;
$modifier ||= '';
die "Bad modifier $modifier" unless $modifier =~ /^[msixge]*$/;
my $sub = eval "sub { s/($search)/$replace/$modifier; }";
die "Error making regex for [$search][$replace][$modifier]: $@" unless $sub;
return $sub;
}
my $search = 'looking';
my $replace = '"find: $1 ="';
my $modifier = 'e';
# Sub can be stored in an array or hash
my $sub = mk_re($search, $replace, $modifier);
$_ = "abc-looking-def";
print "$_\n";
$sub->();
print "$_\n";
While the method using eval
to compile a new substitution is probably the most straightforward, you can create a substitution that is more modular:虽然使用
eval
编译新替换的方法可能是最直接的,但您可以创建一个更模块化的替换:
use warnings;
use strict;
sub subst {
my ($search, $replace, $mod) = @_;
if (my $eval = $mod =~ s/e//g) {
$replace = qq{'$replace'};
$replace = "eval($replace)" for 1 .. $eval;
} else {
$replace = qq{"$replace"};
}
sub {s/(?$mod)$search/$replace/ee}
}
my $sub = subst '(abc)', 'uc $1', 'ise';
local $_ = "my Abc string";
$sub->();
print "$_\n"; # prints "my ABC string"
This is only lightly tested, and it is left as an exercise for the reader to implement other flags like g
这只是简单的测试,它留给读者作为练习来实现其他标志,如
g
Hm, if I had to do it I would do like this:嗯,如果我必须这样做,我会这样做:
use warnings;
use strict;
my @stuff = (
{
search => "this",
replace => "that",
modifier => "g",
},
{
search => "ono",
replace => "wendy",
modifier => "i",
}
);
$_ = "this ono boo this\n";
for my $h (@stuff) {
if ($h->{modifier} eq 'g') {
s/$h->{search}/$h->{replace}/g;
} elsif ($h->{modifier} eq 'i') {
s/$h->{search}/$h->{replace}/i;
}
# etc.
}
print;
There are only so many different modifiers you might want to use so I think this is easy enough.您可能想要使用的修饰符只有这么多,所以我认为这很容易。
You can use eval
for this, but it's awfully messy.您可以为此使用
eval
,但它非常混乱。
Of course s/$search/$replace/
work as you expect.当然
s/$search/$replace/
可以按您的预期工作。 It is the dynamic modifiers that are not straightforward.动态修饰符并不简单。
For the regular match modifiers of pimsx
you can use Perl's Extended Patterns to modify the modifier flags on the fly as part of your pattern.对于
pimsx
的常规匹配修饰符,您可以使用 Perl 的扩展模式来动态修改修饰符标志作为模式的一部分。 These are of the form (?pimsx-imsx)
to turn on / off those modifiers.这些是
(?pimsx-imsx)
来打开/关闭这些修饰符。
For the s//
e
and ee
forms, you can use (?{ perl code})
documented in the same perlre section.对于
s//
e
和ee
形式,您可以使用(?{ perl code})
记录在同一 perlre 部分中。 For all of eval
e
or ee
forms, consider the security of the resulting code!对于所有
eval
e
或ee
形式,请考虑结果代码的安全性!
There is no form to modify global to first match that I am aware of, so global vs first match would need to be separate statements.我知道没有将 global 修改为第一个匹配的形式,因此 global vs first match 需要是单独的语句。
Here's a combination of Kinopiko's answer and eval.这是 Kinopiko 的答案和 eval 的组合。
eval
is used here to generate the lookup table in a controlled and maintainable fashion, and a lookup table is used to save all the if.. elsif.. elsif which are not too fun to look at.这里使用
eval
以可控和可维护的方式生成查找表,并使用查找表保存所有 if.. elsif.. elsif ,它们看起来不太有趣。
(very lightly tested) (非常轻微的测试)
my @stuff = (
{
search => "this",
replace => "that",
modifier => "g",
},
{
search => "ono",
replace => "wendy",
modifier => "i",
}
);
$_ = "this ono boo this\n";
my @modifiers = qw{m s i x g e};
my $s_lookup = {};
foreach my $modifier (@modifiers) {
$s_lookup->{$modifier} = eval " sub { s/\$_[0]/\$_[1]/$modifier } ";
}
for my $h (@stuff) {
$s_lookup->{$h->{modifier}}->($h->{search},$h->{replace});
}
print;
To be fully useful this needs:要完全有用,这需要:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.