Orijinali korurken bir dizede Perl ikamesini nasıl gerçekleştirebilirim?


180

Perl'de, normal bir ifade kullanarak bir dizede değiştirme yapmanın ve orijinali değiştirmeden değeri farklı bir değişkende saklamanın iyi bir yolu nedir?

Ben genellikle sadece yeni bir değişken için dize kopyalayın sonra s///yeni dize yerine yapar regex bağlamak , ama bunu yapmak için daha iyi bir yolu olup olmadığını merak?

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

Yanıtlar:


257

Bu, orijinali değiştirmeden her zaman bir dizenin değiştirilmiş bir kopyasını almak için kullandığım deyimdir:

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

Perl 5.14.0 veya sonraki sürümlerde, yeni /r tahribatsız ikame değiştiricisini kullanabilirsiniz :

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

Not: Yukarıdaki çözümler gde olmadan çalışır . Ayrıca diğer değiştiricilerle de çalışırlar.


6
Sıkı kullanımda olsun veya olmasın. Değişkenlerin minimal kapsamı ++
ysth

Böyle bir şeyin my $new = $_ for $old =~ s/foo/bar;işe yarayıp yaramayacağını merak ediyordum ?
Benoit

2
@Benoit, Sanırım demek istediğini düşünüyorum s/foo/bar/ for my $newstring = $oldstring;, ama çok garip.
ikegami

43

İfade:

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

Şuna eşittir:

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

Alternatif olarak, Perl 5.13.2'den itibaren /rtahribatsız bir ikame yapmak için kullanabilirsiniz :

use 5.013;
#...
my $newstring = $oldstring =~ s/foo/bar/gr;

3
En giyi regex'inizde unuttun mu?
mareoraft

23

Altında use strict, söyle:

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

yerine.


10

Tek katmanlı çözelti, shibboleth olarak iyi koddan daha kullanışlıdır; iyi Perl kodlayıcılar bunu bilir ve anlar, ancak başladığınız iki satırlı kopyala ve değiştir coupletinden çok daha az şeffaf ve okunabilir.

Başka bir deyişle, bunu yapmanın iyi bir yolu zaten yaptığınız yöntemdir . Okunabilirlik pahasına gereksiz kısaltma bir kazanç değildir.


Ah, ancak tek satırlı sürüm, yanlışlıkla yanlış dizeyi değiştirme konusundaki hataya tabi değildir.
08:13

Tek satırlı sürüm, <i> doğru bir şekilde yürütüldüğünde </i>, konu değil, doğru. Ama bu ayrı bir mesele.
Josh Millard

9
Bunun gereksiz kısaltma olduğunu düşünebilirsiniz, ancak bir kez kullanmak için iki kez değişken adı yazmak zorunda kalmak başarısızlık noktalarının iki katıdır. Dili bilen insanlar için mükemmel bir şekilde okunabilir ve hatta <i> Öğrenme Perl </i> kursumuzda bile.
brian d foy

1

5.14 öncesi başka bir çözüm: http://www.perlmonks.org/?node_id=346719 (japonya'nın gönderisine bakın)

Yaklaşımının kullandığı gibi map, diziler için de iyi çalışır, ancak mapgeçici bir dizi oluşturmak için basamaklı gerektirir (aksi takdirde orijinal değiştirilir):

my @orig = ('this', 'this sucks', 'what is this?');
my @list = map { s/this/that/; $_ } map { $_ } @orig;
# @orig unmodified

1

Foo ve bar'dan nefret ediyorum .. Zaten programlamada bu tanımlayıcı olmayan terimleri kim hayal etti?

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
Bunun orijinalden farkı nedir? (Ve sanırım istiyorsun =~ s.)
Teepeemm

Clbuttic hata. Bu kodun gerçek çıktısınewword donotnewword newword donotnewword newword donotnewword
Pascal

2
Bakın ... JoGotta geleneksel ve tanıdık kullansaydı foove barcevabı doğru olurdu. Bir kez daha, bir nedenden dolayı gümrüklerin var olduğunu kanıtlamak ve dersler sadece zor yoldan öğrenilir. ;)
Jon

-1

Perl ile birlikte use strict;yazarsanız, bildirildiğinde bile bir satır sözdiziminin geçerli olmadığını görürsünüz.

İle:

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

Şunları elde edersiniz:

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

Bunun yerine, kullandığınız sözdizimi, bir satır daha uzun olsa da, bunu yapmak için sözdizimsel olarak doğru yoldur use strict;. Benim için kullanmak use strict;artık sadece bir alışkanlık. Ben otomatik olarak yaparım. Herkes yapmalı.

#!/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
Eğer varsa use warnings;yerine -w, size daha fazla kontrol sahibi: Örneğin, geçici bir kod bloğunda uyarıları kapatmak istiyorum.
glenn jackman
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.