Существует ли способ заменить текст встроенным regex, вместо того, чтобы брать текст от переменной и сохранить его в переменной?
Я - новичок жемчуга. Я часто пишу
my $foo = $bar;
$foo =~ s/regex/replacement/;
doStuff($foo)
где я действительно хотел бы записать
doStuff($bar->replace(s/regex/replacement/));
и т.п., вместо того, чтобы использовать временную переменную и три строки.
Существует ли способ сделать это? Очевидно, когда regex является достаточно сложным, имеет смысл разделять его, таким образом, можно лучше объяснить, но когда это справедливо s/\s//g
чувствует себя неправильным создать помехи коду дополнительными переменными.
Вы действительно не можете сделать то, что хотите, потому что функция подстановки возвращает либо 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
останется неизменным.
Это то, что вы хотите?:
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
use Algorithm::Loops "Filter";
# leaves $foo unchanged
doStuff( Filter { s/this/that/ } $foo );
Вы можете использовать блок do {}
, чтобы избежать создания временной переменной в текущей области:
doStuff( do {(my $foo = $bar) =~ s/regex/replacement/; $foo} );
Есть еще один способ: написать свою собственную функцию:
sub replace (
my $variable = shift;
my $substring = shift;
eval "\$variable =~ s${substring};";
return $variable
}
doStuff(replace($foo, "/regex/replace/"));
Это не стоит того для одного вызова и, вероятно, в этом случае только сделает ваш код более запутанным. Однако, если вы делаете это около дюжины раз, возможно, имеет смысл написать для этого свою собственную функцию.