Встройте regex замену в жемчуге

Существует ли способ заменить текст встроенным regex, вместо того, чтобы брать текст от переменной и сохранить его в переменной?

Я - новичок жемчуга. Я часто пишу

my $foo = $bar;
$foo =~ s/regex/replacement/;
doStuff($foo)

где я действительно хотел бы записать

doStuff($bar->replace(s/regex/replacement/));

и т.п., вместо того, чтобы использовать временную переменную и три строки.

Существует ли способ сделать это? Очевидно, когда regex является достаточно сложным, имеет смысл разделять его, таким образом, можно лучше объяснить, но когда это справедливо s/\s//g чувствует себя неправильным создать помехи коду дополнительными переменными.

10
задан Sinan Ünür 26 July 2010 в 00:53
поделиться

5 ответов

Вы действительно не можете сделать то, что хотите, потому что функция подстановки возвращает либо 1, если она сработала, либо пустую строку, если она не сработала. Это означает, что если бы вы сделали так:

doStuff($foo =~ s/regex/replacement/);

Функция doStuff будет использовать в качестве параметра либо 1, либо пустую строку. Нет причин, по которым функция подстановки не могла бы возвращать результирующую строку вместо 1, если бы она работала. Однако это было проектным решением с самых ранних дней Perl. Иначе что бы произошло?

$foo = "widget";
if ($foo =~ s/red/blue/) {
    print "We only sell blue stuff and not red stuff!\n";
}

Результирующей строкой по-прежнему является widget, но подстановка фактически не удалась. Однако если бы подстановка вернула результирующую строку, а не пустую строку, то if все равно было бы истинным.

Тогда рассмотрим следующий случай:

$bar = "FOO!";
if ($bar =~ s/FOO!//) {
   print "Fixed up \'\$bar\'!\n";
}

$bar теперь является пустой строкой. Если бы подстановка вернула результат, она бы вернула пустую строку. Тем не менее, подстановка фактически удалась, и я хочу, чтобы мой if был истинным.

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

if ($bar != replace("$bar", "/FOO!//")) {
   print "Fixed up \'\$bar''!\n";
}

Итак, из-за конструктивного решения Perl (в основном, чтобы лучше имитировать синтаксис awk), нет простого способа сделать то, что вы хотите. Однако вы могли бы сделать следующее:

($foo = $bar) =~ s/regex/replacement/;
doStuff($foo);

Это позволило бы установить $foo без предварительного присвоения ему значения $bar. $bar останется неизменным.

14
ответ дан 3 December 2019 в 16:28
поделиться

Это то, что вы хотите?:

my $foo = 'Replace this with that';
(my $bar = $foo) =~ s/this/that/;
print "Foo: $foo\nBar: $bar\n";

Печатает:

Foo: Replace this with that
Bar: Replace that with that
0
ответ дан 3 December 2019 в 16:28
поделиться
use Algorithm::Loops "Filter";

# leaves $foo unchanged
doStuff( Filter { s/this/that/ } $foo );
5
ответ дан 3 December 2019 в 16:28
поделиться

Вы можете использовать блок do {} , чтобы избежать создания временной переменной в текущей области:

doStuff( do {(my $foo = $bar) =~ s/regex/replacement/; $foo} );
2
ответ дан 3 December 2019 в 16:28
поделиться

Есть еще один способ: написать свою собственную функцию:

sub replace (
    my $variable = shift;
    my $substring = shift;

    eval "\$variable =~ s${substring};";
    return $variable
}

doStuff(replace($foo, "/regex/replace/"));

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

-1
ответ дан 3 December 2019 в 16:28
поделиться
Другие вопросы по тегам:

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