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

142

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

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

$newstring = $oldstring;
$newstring =~ s/foo/bar/g;
Теги:
replace

7 ответов

190
Лучший ответ

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

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

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

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

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

  • 6
    Будь или не под строгим использованием. Минимальная область видимости переменных ++
  • 0
    Мне было интересно, если что-то вроде my $new = $_ for $old =~ s/foo/bar; должно сработать?
Показать ещё 1 комментарий
43

Заявление:

(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
    Вы забыли g в вашем главном регулярном выражении?
19

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

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

вместо.

8

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

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

  • 0
    Ах, но однострочная версия не подвержена ошибке в вопросе непреднамеренного изменения неправильной строки.
  • 0
    Однострочная версия, <i> если правильно выполнено </ i>, не подчиняется, true. Но это отдельная проблема.
Показать ещё 1 комментарий
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
  • 2
    Чем это отличается от оригинала? (И я думаю, что вы хотите =~ s .)
  • 0
    Грубая ошибка. Фактический результат этого кода - newword donotnewword newword donotnewword newword donotnewword
Показать ещё 1 комментарий
0

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

Если вы пишете 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";
  • 0
    Если вы use warnings; вместо -w вы получаете больший контроль: например, если вы хотите временно отключить предупреждения в блоке кода.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню