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

regex perl replace

181857 просмотра

7 ответа

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

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

$newstring = $oldstring;
$newstring =~ s/foo/bar/g;
Автор: kaybenleroll Источник Размещён: 22.10.2019 02:54

Ответы (7)


239 плюса

Решение

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

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

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

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

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

Автор: John Siracusa Размещён: 22.08.2008 05:08

42 плюса

Заявление:

(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;
Автор: Pat Размещён: 23.08.2008 08:53

21 плюса

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

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

вместо.

Автор: Sam Kington Размещён: 15.09.2008 12:49

9 плюса

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

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

Автор: Josh Millard Размещён: 18.09.2008 05:13

1 плюс

Другое решение до 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
Автор: textral Размещён: 25.05.2017 05:15

1 плюс

Я ненавижу 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
Автор: JoGotta Размещён: 06.03.2016 04:07

-1 плюса

Если вы напишите на 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";
Автор: Tim Kennedy Размещён: 11.09.2008 03:51
32x32