简体   繁体   English

如何在替换中使用变量作为修饰符

[英]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// eee形式,您可以使用(?{ perl code})记录在同一 perlre 部分中。 For all of eval e or ee forms, consider the security of the resulting code!对于所有eval eee形式,请考虑结果代码的安全性!

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:要完全有用,这需要:

  1. combinations of possible modifiers可能的修饰符的组合
  2. sort function on the lookup table so 'msi' combination and 'mis' combination will go to the same key.查找表上的排序功能,因此“msi”组合和“mis”组合将转到相同的键。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM