Perlでforeachを使うときのメモ
Perlのforeach
はfor
と同義語だそうです。(*1)
つまり、foreach
でもfor
でも好きな方を使って良いみたいです。
それはさておき、foreach
で取得した変数を書き換えたらどうなるんだっけ?
って思って、ちょっと試してみました。
use v5.10; use strict; use warnings; my @foo = qw/a b c/; { my @bar = @foo; foreach (@bar) { s/[abc]/x/; # $_ =~ s/[abc]/x/; } say join(',', @foo), ' >>> ', join(',', @bar); } { my @bar = @foo; foreach my $str (@bar) { $str =~ s/[abc]/x/; } say join(',', @foo), ' >>> ', join(',', @bar); } { my @bar = @foo; foreach my $str (@bar) { (my $tmp = $str) =~ s/[abc]/x/; } say join(',', @foo), ' >>> ', join(',', @bar); }
実行すると、こんな感じ。
$ perl aaa.pl
a,b,c >>> x,x,x
a,b,c >>> x,x,x
a,b,c >>> a,b,c
map
やgrep
で、$_
を書き換えるのは行儀が悪いっていうのは知ってたけど、
for
/foreach
でもアレですね。
普通に添字を使って書き換えるくらいなら、
上記の方法で書き換えるっていうのでも良いけれど、
だったらmap
を使って、変更後の配列を作った方が良い気がします。
use v5.10; use strict; use warnings; my @foo = qw/a b c/; { my @bar = @foo; for (my $i=0; $i<scalar(@bar); $i++) { $bar[$i] =~ s/[abc]/x/; } say join(',', @foo), ' >>> ', join(',', @bar); } { my @bar = @foo; @bar = map { (my $str = $_) =~ s/[abc]/x/; $str; } @bar; say join(',', @foo), ' >>> ', join(',', @bar); }
実行すると、こんな感じ。
$ perl bbb.pl
a,b,c >>> x,x,x
a,b,c >>> x,x,x
書き換えてはみたものの、意図が伝わり難いコードになっちゃいました。。。
お題が良くなかったですかねーって思って、
perldoc.jpを眺めてたら良いものを見つけました!
非破壊置換修飾子
s///r
(*2)を使うと、こう書ける。
use v5.14; # <<< not v5.10 use strict; use warnings; my @foo = qw/a b c/; my @bar = map { s/[abc]/x/r; } @foo; say join(',', @foo), ' >>> ', join(',', @bar);
実行すると、こんな感じ。
$ perl ccc.pl
a,b,c >>> x,x,x
おお!これは、便利!!
Perl v5.14.0から入ったみたいですね。
非破壊的置換 – perl v5.14.0 での変更点
http://perldoc.jp/docs/perl/5.14.0/perl5140delta.pod#Non-destructive32substitution
という訳で、ちょっと賢くなりました。
おしまい。
(*1) Perl の文法(perldoc.jp)
(*2) Perl の正規表現のチュートリアル(perldoc.jp)
Leave a Comment