В 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/;
Является эквивалентным:
my $newstring = $oldstring;
$newstring =~ s/foo/bar/g;
В качестве альтернативы, с Perl 5.13.2 вы можете использовать /r
для выполнения неразрушающей замены:
use 5.013;
#...
my $newstring = $oldstring =~ s/foo/bar/gr;
g
в вашем главном регулярном выражении?
Под use strict
, скажем:
(my $new = $original) =~ s/foo/bar/;
вместо.
Однострочное решение более полезно как шибболет, чем хороший код; хорошие кодеки Perl узнают об этом и поймут это, но он будет гораздо менее прозрачным и читаемым, чем двухстрочный кумир-модификатор, с которого вы начинаете.
Другими словами, хороший способ сделать это - это то, как вы выполняете это уже. Ненужная репликация за счет удобочитаемости - это не победа.
Я ненавижу foo и bar.. кто в любом случае придумывал эти не описательные термины в программировании?
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
=~ s
.)
newword donotnewword newword donotnewword newword donotnewword
Другое решение до 5.14: http://www.perlmonks.org/?node_id=346719 (см. сообщение japhy)
Поскольку его подход использует map
, он также хорошо работает для массивов, но требует каскадирования map
для создания временного массива (в противном случае оригинал будет изменен):
my @orig = ('this', 'this sucks', 'what is this?');
my @list = map { s/this/that/; $_ } map { $_ } @orig;
# @orig unmodified
Если вы пишете 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";
use warnings;
вместо -w
вы получаете больший контроль: например, если вы хотите временно отключить предупреждения в блоке кода.
my $new = $_ for $old =~ s/foo/bar;
должно сработать?