Jak wykonać podstawianie Perla na łańcuchu przy zachowaniu oryginału?

W Perlu, jaki jest dobry sposób na zastąpienie łańcucha za pomocą wyrażenia regularnego i zapisanie wartości w innej zmiennej, bez zmiany oryginału?

Zwykle po prostu kopiuję łańcuch do nowej zmiennej, a następnie wiążę go do s/// regex, który zastępuje nowy łańcuch, ale zastanawiałem się, czy jest lepszy sposób, aby to zrobić?

$newstring = $oldstring;
$newstring =~ s/foo/bar/g;
Author: the Tin Man, 2008-08-22

7 answers

Jest to idiom, którego zawsze używałem, aby uzyskać zmodyfikowaną kopię łańcucha bez zmiany oryginału:

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

W Perlu 5.14.0 lub nowszym, możesz użyć nowego /r nieniszczący modyfikator podstawienia:

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

Uwaga: powyższe rozwiązania działają również bez g. Działają również z innymi modyfikatorami.

 214
Author: John Siracusa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-22 16:41:11

Wypowiedź:

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

Co jest równoważne:

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

Alternatywnie, od wersji Perla 5.13.2 możesz użyć /r do wykonania nieniszczącej substytucji:

use 5.013;
#...
my $newstring = $oldstring =~ s/foo/bar/gr;
 41
Author: Pat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-30 17:13:22

Pod use strict, powiedz:

(my $new = $original) =~ s/foo/bar/;
Zamiast tego.
 19
Author: Sam Kington,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-01 18:09:37

Rozwiązanie Jednowierszowe jest bardziej przydatne jako shibbolet niż dobry kod; dobrzy koderzy Perla będą go znać i rozumieć, ale jest znacznie mniej przejrzysty i czytelny niż dwuwiersz kopiowania i zmiany w dwóch liniach, od których zaczynasz.

Innymi słowy, dobrym sposobem na to jest sposób, w jaki już to robisz. Niepotrzebna zwięzłość kosztem czytelności nie jest wygraną.

 9
Author: Josh Millard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-28 20:29:12

Nienawidzę foo i bar .. kto w ogóle wymyślił te nieopisowe terminy w programowaniu?

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
 1
Author: JoGotta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-05 19:17:53

Inne rozwiązanie przed 5.14: http://www.perlmonks.org/?node_id=346719 (Zobacz post japhy)

Ponieważ jego podejście wykorzystuje map, działa również dobrze dla tablic, ale wymaga kaskadowania map do wytworzenia tymczasowej tablicy (w przeciwnym razie oryginał zostałby zmodyfikowany):

my @orig = ('this', 'this sucks', 'what is this?');
my @list = map { s/this/that/; $_ } map { $_ } @orig;
# @orig unmodified
 0
Author: textral,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-25 06:14:25

Jeśli napiszesz Perl za pomocą use strict;, to przekonasz się, że składnia jednej linii nie jest poprawna, nawet jeśli jest zadeklarowana.

Z:

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

Otrzymujesz:

Can't declare scalar assignment in "my" at script.pl line 7, near ") =~"
Execution of script.pl aborted due to compilation errors.

Zamiast tego, składnia, której używasz, podczas gdy linia jest dłuższa, jest poprawnym składniowo sposobem na to za pomocą use strict;. Dla mnie używanie use strict; jest teraz tylko nawykiem. Robię to automatycznie. Każdy powinien.

#!/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";
 -1
Author: Tim Kennedy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-01 18:11:37