Как я могу использовать s Perl///в выражении?

Я страдал от головной боли, ища это: Как Вы используете s///в выражении в противоположность присвоению. Для разъяснения, что я имею в виду я ищу жемчуг, эквивалентный из re.sub Python (...) при использовании в следующем контексте:

newstring = re.sub('ab', 'cd', oldstring)

Единственным путем я знаю, как сделать, это в жемчуге до сих пор:

$oldstring =~ s/ab/cd/;
$newstring = $oldstring;

Отметьте дополнительное присвоение.

7
задан brian d foy 19 April 2010 в 22:52
поделиться

5 ответов

Похоже, вы неправильно понимаете, как работает = ~ . = ~ - это оператор привязки, который связывает переменную с оператором регулярного выражения. Он не выполняет никаких заданий.

Все операторы регулярного выражения по умолчанию работают с переменной темы $ _ , поэтому s / foo / bar /; совпадает с $ _ = ~ s / foo / bar /; . Присваивания не происходит. Переменная темы преобразована.

Случай аналогичен при работе с любой другой переменной. $ var = ~ s / foo / bar /; преобразует $ var , заменяя первый экземпляр foo на bar . Присваивания не происходит.

Лучший совет, который я могу вам дать, - писать Python на Python и Perl на Perl. Не ожидайте, что эти два языка будут одинаковыми.

Вы могли бы поступить так, как предлагает DVK, и написать подпрограмму, которая будет воспроизводить поведение замены, к которому вы привыкли.

Или вы можете попробовать какой-нибудь идиоматический Perl. Основываясь на вашем выраженном желании применить несколько преобразований в одной строке, я привел пару примеров, которые могут оказаться полезными.

Здесь я использую цикл for над одним элементом, чтобы актуализировать $ var и применить множество жестко запрограммированных преобразований:

for( $var ) {
    s/foo/bar/;
    s/fizz/buzz/;
    s/whop/bop-a-loo-bop/;
    s/parkay/butter/;
    s/cow/burger/;
}

Или, может быть, вам нужно применить переменную группу преобразований . Я определяю подпрограмму для перебора списка ссылок на массивы, которые определяют старые / новые пары преобразований. В этом примере используется обработка аргументов Perl, ориентированная на список, для обработки любого количества преобразований.

my $foo = transform(
    'abcd' =>
    [ 'a',  'b'    ], 
    [ 'bb', 'c'    ],
    [ 'cc', 'd'    ],
    [ 'dd', 'DONE' ],
);

sub transform {
    my $var = shift;
    for (@_ ) {
        my ($old, $new) = @$_;
        $var =~ s/$old/$new/;
    }

    return $var;
}

И, наконец, немного возиться с предоставлением версии преобразования, изменяющей его первый аргумент:

my $foo = 'abcd';

transform_in_place(
    $foo =>
    [ 'a',  'b'    ], 
    [ 'bb', 'c'    ],
    [ 'cc', 'd'    ],
    [ 'dd', 'DONE' ],
);

print "$foo\n";

sub transform_in_place {
    for my $i (1..$#_ ) {
        my ($old, $new) = @{$_[$i]};
        $_[0] =~ s/$old/$new/;
    }
}

Для моего собственного проекта я, вероятно, использовал бы один из первых двух вариантов в зависимости от потребностей конкретной проблемы.

7
ответ дан 6 December 2019 в 06:23
поделиться

Подстановка регулярных выражений Perl всегда выполняется "на месте". Поэтому вам нужно скопировать строку в новую переменную и работать с новой переменной:

(my $newstring = $oldstring) =~ s/ab/cd/;
7
ответ дан 6 December 2019 в 06:23
поделиться

Вы можете использовать ($ new = $ old) = ~ s / something / whateverelse /; для точно такой же функциональности, которую вы ищете:

use strict;
my $old = "OLD";
my $new;
($new = $old) =~ s/OLD/NEW/;
print "old=$old, new=$new";

Производит:

old=OLD, new=NEW

Именно то, что вы хотите

Если вы ищете функцию, вы можете просто определить ваше собственное, чтобы избежать присваивания:

use strict;
sub re_sub { 
   my ($find, $replace, $old) = @_;
   my $new = $old;
   $new =~ s/$find/$replace/;
   return $new;
}

my $old = "ab";
my $new = re_sub('ab', 'cd', $old);
print "new=$new\n";

Результаты в new = cd .

11
ответ дан 6 December 2019 в 06:23
поделиться

Основываясь на этом, правильно ли я предполагаю, что вы не можете иметь два s /// в одной строке, одна из которых использует результат другой, без промежуточных присваиваний? - mikeY

Да, вы правы. Если вы хотите применить несколько замен к одной и той же строке, я бы сделал

    $newstring = $oldstring ;
    $newstring  =~ s/ab/cd/ ;
    $newstring  =~ s/xx/yy/ ;

Следующее не сработает, потому что s // возвращает количество сделанных замен, а не измененная строка.

    $newstring = $oldstring) =~ s/ab/cd/ =~ s/xx/yy/ ;

Таким образом, операции регулярных выражений Perl сильно отличаются от операций Python, и вам лучше попытаться изучить, что Perl делает с нуля, а не пытаться сопоставить концепции Python с Perl

1
ответ дан 6 December 2019 в 06:23
поделиться

Вы хотите, чтобы результатом подстановки была $ newstring, верно?

Примерно так:

($newstring = $oldstring) =~ s/ab/cd;

Должно сработать. Присваивание устанавливает $ newstring в $ oldstring , а затем вычисляет значение $ newstring , на которое действует подстановка.

2
ответ дан 6 December 2019 в 06:23
поделиться
Другие вопросы по тегам:

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