Как выполнить подстановку Perl для строки, сохранив оригинал? - PullRequest
162 голосов
/ 22 августа 2008

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

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

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

Ответы [ 7 ]

230 голосов
/ 22 августа 2008

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

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

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

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

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

42 голосов
/ 23 августа 2008

утверждение:

(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;
20 голосов
/ 15 сентября 2008

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

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

вместо.

9 голосов
/ 18 сентября 2008

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

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

1 голос
/ 25 мая 2017

Другое решение до 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
1 голос
/ 06 марта 2016

Я ненавижу 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
0 голосов
/ 11 сентября 2008

Если вы напишите 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";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...