5

有没有办法在替换中使用变量作为修饰符?

my $search = 'looking';
my $replace = '"find: $1 ="';
my $modifier = 'ee';

s/$search/$replace/$modifier;

我需要使用哈希数组来使用不同的修饰符进行批量搜索替换。

4

5 回答 5

4

eval如果您戴上安全护目镜和除零套装,您可以使用。

例如:

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";
于 2010-07-13T14:56:37.163 回答
4

虽然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"

这只是经过轻微测试,它留给读者作为练习来实现其他标志,如g

于 2010-07-13T18:52:29.297 回答
3

嗯,如果我必须这样做,我会这样做:

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;

您可能想要使用的不同修饰符只有这么多,所以我认为这很容易。

您可以使用eval它,但它非常混乱。

于 2010-07-13T15:42:52.840 回答
2

当然s/$search/$replace/可以按您的预期工作。动态修饰符并不简单。

对于您的常规匹配修饰符pimsx您可以使用 Perl 的扩展模式来动态修改修饰符标志作为模式的一部分。这些是(?pimsx-imsx)打开/关闭这些修饰符的形式。

对于s// eee表单,您可以使用(?{ perl code})同一 perlre 部分中的文档。对于所有eval eoree形式,请考虑生成代码的安全性!

据我所知,没有将全局修改为第一个匹配的形式,因此全局与第一个匹配需要是单独的语句。

于 2010-07-13T19:02:18.090 回答
2

这是 Kinopiko 的答案和评估的组合。

eval此处用于以受控和可维护的方式生成查找表,并且查找表用于保存所有看起来不太有趣的 if.. elsif.. elsif。

(非常轻微的测试)

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; 

要完全有用,这需要:

  1. 可能的修饰符的组合
  2. 查找表上的排序功能,因此“msi”组合和“mis”组合将转到同一个键。
于 2010-07-13T21:56:40.487 回答