Как мне выполнить замену Perl в строке, сохранив оригинал?
Вопрос
В Perl, каков хороший способ выполнить замену строки с помощью регулярного выражения и сохранить значение в другой переменной, не изменяя исходную?
Обычно я просто копирую строку в новую переменную, а затем привязываю ее к s///
регулярное выражение, которое выполняет замену в новой строке, но мне было интересно, есть ли лучший способ сделать это?
$newstring = $oldstring;
$newstring =~ s/foo/bar/g;
Решение
Это идиома, которую я всегда использовал, чтобы получить измененную копию строки без изменения оригинала:
(my $newstring = $oldstring) =~ s/foo/bar/g;
В perl 5.14.0 или более поздней версии вы можете использовать новый /r
модификатор неразрушающей замены:
my $newstring = $oldstring =~ s/foo/bar/gr;
Примечание:Вышеприведенные решения работают без g
слишком.Они также работают с любыми другими модификаторами.
Другие советы
Заявление:
(my $newstring = $oldstring) =~ s/foo/bar/g;
Что эквивалентно:
my $newstring = $oldstring;
$newstring =~ s/foo/bar/g;
В качестве альтернативы, начиная с Perl 5.13.2, вы можете использовать /r
чтобы выполнить неразрушающую замену:
use 5.013;
#...
my $newstring = $oldstring =~ s/foo/bar/gr;
Под use strict
, сказать:
(my $new = $original) =~ s/foo/bar/;
вместо этого.
Однострочное решение более полезно в качестве шибболета, чем хороший код;хорошие программисты на Perl будут знать это и понимать, но это гораздо менее прозрачно и читабельно, чем двухстрочный куплет с копированием и изменением, с которого вы начинаете.
Другими словами, хороший способ сделать это - это то, как вы уже делаю это.Излишняя лаконичность в ущерб удобочитаемости - это еще не победа.
Другое решение, разработанное до версии 5.14: http://www.perlmonks.org/?node_id=346719 (см. сообщение Джефи)
В качестве своего подхода использует map
, это также хорошо работает для массивов, но требует каскадирования map
для создания временного массива (в противном случае оригинал был бы изменен):
my @orig = ('this', 'this sucks', 'what is this?');
my @list = map { s/this/that/; $_ } map { $_ } @orig;
# @orig unmodified
Я ненавижу фу и бар ..кто вообще придумал эти не описательные термины в программировании?
my $oldstring = "replace donotreplace replace donotreplace replace donotreplace";
my $newstring = $oldstring;
$newstring =~ s/replace/newword/g; # inplace replacement
print $newstring;
%: newword donotreplace newword donotreplace newword donotreplace
Если вы пишете Perl с use strict;
, тогда вы обнаружите, что синтаксис в одну строку недопустим, даже если он объявлен.
С:
my ($newstring = $oldstring) =~ s/foo/bar/;
Вы получаете:
Can't declare scalar assignment in "my" at script.pl line 7, near ") =~"
Execution of script.pl aborted due to compilation errors.
Вместо этого синтаксис, который вы использовали, хотя и на строку длиннее, является синтаксически правильным способом сделать это с помощью use strict;
.Для меня, используя use strict;
теперь это просто привычка.Я делаю это автоматически.Каждый должен это делать.
#!/usr/bin/env perl -wT
use strict;
my $oldstring = "foo one foo two foo three";
my $newstring = $oldstring;
$newstring =~ s/foo/bar/g;
print "$oldstring","\n";
print "$newstring","\n";