元の文字列を維持しながら、文字列にPerl置換を実行するにはどうすればよいですか?


180

Perlでは、正規表現を使用して文字列の置換を実行し、元の値を変更せずに別の変数に値を格納するための良い方法は何ですか?

私は通常、文字列を新しい変数にコピーし、それをs///新しい文字列の置換を行う正規表現にバインドしますが、これを行うより良い方法があるかどうか疑問に思っていましたか?

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

回答:


257

これは、元の文字列を変更せずに文字列の変更されたコピーを取得するために常に使用してきたイディオムです。

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

perl 5.14.0以降では、新しい/r 非破壊置換修飾子を使用できます。

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

注:上記のソリューションはgあまりにも機能します。また、他の修飾子でも機能します。


6
厳密に使用されているかどうか。変数の最小限のスコープ++
ysth '19

私は何かmy $new = $_ for $old =~ s/foo/bar;がうまくいくのだろうかと思っていましたか?
Benoit

2
@Benoit、私はs/foo/bar/ for my $newstring = $oldstring;それがうまくいくことを意味すると信じていますが、それははるかに奇妙です。
池上

43

ステートメント:

(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;

3
あなたgはあなたのトップの正規表現を忘れましたか?
mareoraft 2014


10

ワンライナーソリューションは、優れたコードよりもシボレスとして有用です。優れたPerlプログラマーはそれを知って理解しますが、最初の2行のコピーと変更のカプレットよりもはるかに透過的で読みにくいです。

言い換えれば、これを行うための良い方法は、すでにそれを行っている方法です。読みやすさを犠牲にして不必要に簡潔にすることは勝ちではありません。


ああ、でも、1行バージョンは、誤って誤った文字列を変更する問題のエラーの影響を受けません。
ys

1行のバージョンは、<i>正しく実行された場合</ i>、対象ではありません、trueです。しかし、それは別の問題です。
ジョシュミラード

9
不必要な簡潔さだと思うかもしれませんが、変数名を2度入力して1度使用するのは、障害箇所の数の2倍です。この言語は、その言語を知っている人にとっては完全に読みやすく、<i> Perlの学習</ i>コースにも含まれています。
ブライアン・ド・フォイ2008

1

5.14より前の別のソリューション:http : //www.perlmonks.org/? node_id=346719 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

私は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。)
Teepeemm

陰部の間違い。そのコードの実際の出力はnewword donotnewword newword donotnewword newword donotnewword
Pascal

2
参照してください... JoGottaが伝統的で使い慣れたfooandを使用していた場合bar、彼の答えは正確だっただろう。もう一度、理由があって慣習が存在することを証明し、レッスンは難しい方法でのみ学習されます。;)
Jon

-1

Perlをuse strict;で記述した場合、宣言されていても、1行の構文が無効であることがわかります。

と:

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.

代わりに、これまで使用してきた構文は、1行長くなりますが、で構文的に正しい方法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";

1
use warnings;代わりに-w、より強力な制御が得られます。たとえば、コードのブロックで警告を一時的にオフにする場合などです。
グレン・ジャックマン、2009年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.