Как использовать переменную в качестве модификатора в замене

Существует ли способ использовать переменную в качестве модификатора в замене?

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

s/$search/$replace/$modifier;

Я должен использовать массив хешей для создания объемной поисковой замены различными модификаторами.

5
задан dawg 13 July 2010 в 19:21
поделиться

5 ответов

Хм, если бы мне пришлось это сделать, я бы сделал так:

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 , но это ужасно беспорядочно.

3
ответ дан 18 December 2019 в 11:52
поделиться

Вы можете использовать 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";
4
ответ дан 18 December 2019 в 11:52
поделиться

Хотя метод, использующий 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

4
ответ дан 18 December 2019 в 11:52
поделиться

Конечно, s/$search/$replace/ работают так, как вы ожидаете. С динамическими модификаторами все не так просто.

Для регулярного соответствия модификаторов из pimsx вы можете использовать расширенные шаблоны Perl, чтобы изменять флаги модификаторов на лету как часть вашего шаблона. Они имеют вид (?pimsx-imsx) для включения/выключения этих модификаторов.

Для форм s// e и ee вы можете использовать (?{код perl}), документированные в том же разделе perlre. Для всех форм eval e или ee подумайте о безопасности получаемого кода!

Насколько я знаю, нет формы для изменения глобального на первое совпадение, поэтому глобальное и первое совпадение должны быть отдельными утверждениями.

2
ответ дан 18 December 2019 в 11:52
поделиться

Вот комбинация ответа Kinopiko и eval.

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' попадали на одну и ту же клавишу.
2
ответ дан 18 December 2019 в 11:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: