Как выполнить подстановку Perl в строке при сохранении оригинала?

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

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

$newstring = $oldstring;
$newstring =~ s/foo/bar/g;

Ответ 1

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

(my $newstring = $oldstring) =~ s/foo/bar/g;

В perl 5.14.0 или новее вы можете использовать новый /r неразрушающий модификатор замещения:

my $newstring = $oldstring =~ s/foo/bar/gr; 

Примечание. Вышеупомянутые решения работают без g. Они также работают с любыми другими модификаторами.

Ответ 2

Заявление:

(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;

Ответ 3

Под use strict, скажем:

(my $new = $original) =~ s/foo/bar/;

вместо.

Ответ 4

Однострочное решение более полезно как шибболет, чем хороший код; хорошие кодеки Perl узнают об этом и поймут это, но он будет гораздо менее прозрачным и читаемым, чем двухстрочный кумир-модификатор, с которого вы начинаете.

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

Ответ 5

Я ненавижу 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

Ответ 6

Другое решение до 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

Ответ 7

Если вы пишете 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";