AAやBB等、同じ文字が連続する場合に一致させるには、正規表現の後方参照を使います。
後方参照とは、括弧の中にマッチしたテキストを表します。
例えば、\1は最初に一致した括弧の文字を表し、\2は2番めに一致した括弧の文字を表します。
my @strings = (
"すす、好きです",
"あ、愛してる",
"ABBA",
"Change");
foreach my $aStr(@strings) {
if ($aStr=~/(\S)\1/) {
print "$aStr\n";
}
}
上記では、スペース以外の文字を表す\Sを括弧でくくり、後方参照\1で一致した括弧の文字と一致するかをチェックすることで文字の連続をチェックしています。
結果は以下のようになります。
すす、好きです
ABBA
2013年3月18日月曜日
エラー発生時に自動的に死亡するようにする
Perlのバージョン5.10以降からは「use autodie」を付けることでファイルIO等、エラーが発生した時に自動的に死亡するようにすることができるようになりました。
従来
open $IN, "<:utf8", $ARGV[0] or die "Can't open file $!"; # ファイルがオープン出来なければ死亡することを明示
上記ではオープンのたびに正常にオープンできたかチェックし、エラーなら死亡するようにしています。
新しいバージョン
use autodie;
当然、死亡理由等、必要な情報を吐き出して死亡してくれます。
従来
open $IN, "<:utf8", $ARGV[0] or die "Can't open file $!"; # ファイルがオープン出来なければ死亡することを明示
上記ではオープンのたびに正常にオープンできたかチェックし、エラーなら死亡するようにしています。
新しいバージョン
use autodie;
open $IN, "<:utf8", $ARGV[0]; # もうエラーについて書かなくても良い!
当然、死亡理由等、必要な情報を吐き出して死亡してくれます。
出力フォーマットを指定する
Perlで文字列を出力するには、printを使いますが、フォーマットを指定して出力するには、printfを使います。
%dは10進整数を表示し、%sは文字を表示します。
my $num=55.55;
printf "数値:%d 文字:%s\n", $num, $num;
%dは小数以下は切り捨てられます。結果は以下のようになります。
数値:55 文字:55.55
%gは、perlが小数、整数、浮動少数等、状況に応じて適宜判断してくれます。
printf "適宜当てはめた値:%g %g %g\n", 0.5, 0.0000000234567, 10;
結果は以下のようになります。
適宜当てはめた値:0.5 2.34567e-08 10
文字(%s)や整数(%d)等、%とdやs等の間に数字を指定することで桁数を指定できます。
my $num=55.55;
printf "数値:%6d 文字:%10s 適宜当てはめた値:%6g\n", $num, $num, $num;
結果は以下のようになります。
数値: 55 文字: 55.55 適宜当てはめた値: 55.55
上記は桁数を指定したので、黄色い部分にスペースが挿入されています。
更に、空白ではなく0で埋めたり、左寄せしたり、四捨五入もできます。パーセント自体を出力する時は、%%と2個連続させます。
my $num=55.55;
printf "0で埋める:%06d 左寄せ:%-6d 四捨五入または浮動少数:%4.0f %%\n", $num, $num, $num;
結果は以下のようになります。
0で埋める:000055 左寄せ:55 四捨五入または浮動少数:56 %
%dは10進整数を表示し、%sは文字を表示します。
my $num=55.55;
printf "数値:%d 文字:%s\n", $num, $num;
%dは小数以下は切り捨てられます。結果は以下のようになります。
数値:55 文字:55.55
%gは、perlが小数、整数、浮動少数等、状況に応じて適宜判断してくれます。
printf "適宜当てはめた値:%g %g %g\n", 0.5, 0.0000000234567, 10;
結果は以下のようになります。
適宜当てはめた値:0.5 2.34567e-08 10
文字(%s)や整数(%d)等、%とdやs等の間に数字を指定することで桁数を指定できます。
my $num=55.55;
printf "数値:%6d 文字:%10s 適宜当てはめた値:%6g\n", $num, $num, $num;
結果は以下のようになります。
数値: 55 文字: 55.55 適宜当てはめた値: 55.55
上記は桁数を指定したので、黄色い部分にスペースが挿入されています。
更に、空白ではなく0で埋めたり、左寄せしたり、四捨五入もできます。パーセント自体を出力する時は、%%と2個連続させます。
my $num=55.55;
printf "0で埋める:%06d 左寄せ:%-6d 四捨五入または浮動少数:%4.0f %%\n", $num, $num, $num;
結果は以下のようになります。
0で埋める:000055 左寄せ:55 四捨五入または浮動少数:56 %
静的変数
Perlで静的変数(C言語でいうところのstatic変数)を使用するには、stateを使用します。
Perlのバージョン5.10以降の機能なのでuse 5.010を付けることに注意が必要です。
また、バージョン5.14時点ではstateを配列(リスト)や辞書(ハッシュ)につけることはできないようです。
#!/opt/local/bin/perl
use warnings;
use 5.010;
print "号令!\n";
while (my $line = <STDIN>) {
if (!defined($line)) { last; };
&marine;
}
sub marine {
state $sailor_number = 0;
$sailor_number++;
print "I'm sailor $sailor_number!\n";
}
結果は以下のようになります。
号令!
I'm sailor 1!
I'm sailor 2!
I'm sailor 3!
I'm sailor 4!
I'm sailor 5!
I'm sailor 6!
I'm sailor 7!
Perlのバージョン5.10以降の機能なのでuse 5.010を付けることに注意が必要です。
また、バージョン5.14時点ではstateを配列(リスト)や辞書(ハッシュ)につけることはできないようです。
#!/opt/local/bin/perl
use warnings;
use 5.010;
print "号令!\n";
while (my $line = <STDIN>) {
if (!defined($line)) { last; };
&marine;
}
sub marine {
state $sailor_number = 0;
$sailor_number++;
print "I'm sailor $sailor_number!\n";
}
結果は以下のようになります。
号令!
I'm sailor 1!
I'm sailor 2!
I'm sailor 3!
I'm sailor 4!
I'm sailor 5!
I'm sailor 6!
I'm sailor 7!
foreachで使用した変数は元に戻る
Perlでは、foreachループで使用した変数は自動的に元の値に戻ります。
例えば、
@strings = qw(neko inu tori);
$str = "empty";
foreach $str(@strings) {
print "str=$str\n";
}
print "str=$str\n"; # ループ内の変更は保持されない
結果は以下のようになります。
str=neko
str=inu
str=tori
str=empty
$strの値はループ内で変更されますが、ループを抜けると元の値に戻っています。
当たり前ですが、for文ではこのようなことはありません。
念のためfor文のループ処理も書いておきます。
@strings = qw(neko inu tori);
$count = 0;
$str = "empty";
for($count=0 ; $count < scalar(@strings) ; $count++) {
$str = $strings[$count];
print "str=$str\n";
}
print "count=$count\n"; # ループ内の変更が反映される
print "str=$str\n"; # ループ内の変更が反映される
結果は以下のようになります。
str=neko
str=inu
str=tori
count=3
str=tori
for文のループ内で変更された$strと$countの値は、ループを抜けても最後に格納された値が反映されています。(自動的に元には戻りません。)
例えば、
@strings = qw(neko inu tori);
$str = "empty";
foreach $str(@strings) {
print "str=$str\n";
}
print "str=$str\n"; # ループ内の変更は保持されない
結果は以下のようになります。
str=neko
str=inu
str=tori
str=empty
$strの値はループ内で変更されますが、ループを抜けると元の値に戻っています。
当たり前ですが、for文ではこのようなことはありません。
念のためfor文のループ処理も書いておきます。
@strings = qw(neko inu tori);
$count = 0;
$str = "empty";
for($count=0 ; $count < scalar(@strings) ; $count++) {
$str = $strings[$count];
print "str=$str\n";
}
print "count=$count\n"; # ループ内の変更が反映される
print "str=$str\n"; # ループ内の変更が反映される
結果は以下のようになります。
str=neko
str=inu
str=tori
count=3
str=tori
for文のループ内で変更された$strと$countの値は、ループを抜けても最後に格納された値が反映されています。(自動的に元には戻りません。)
2013年3月8日金曜日
連想配列からキーと値の組みを取り出す
連想配列(ハッシュ)からキーと値を一度に取り出すには、eachを使います。
%hash = (
'D' => 4,
'E' => 9,
'C' => 1,
'A' => 5,
'B' => 8,
);
while (@key_value = each %hash) { # 辞書からキーと値の組みを取り出す
print "$key_value[0]:$key_value[1]\n";
}
eachでは「キー」と「値」の配列が取得できます。
結果は以下のようになります。
A:5
C:1
D:4
B:8
E:9
%hash = (
'D' => 4,
'E' => 9,
'C' => 1,
'A' => 5,
'B' => 8,
);
while (@key_value = each %hash) { # 辞書からキーと値の組みを取り出す
print "$key_value[0]:$key_value[1]\n";
}
eachでは「キー」と「値」の配列が取得できます。
結果は以下のようになります。
A:5
C:1
D:4
B:8
E:9
2013年3月7日木曜日
連想配列(ハッシュ)をキー順にソート
ハッシュをキー順にソートするには、以下のようにします。
%hash = (
'D' => 4,
'E' => 9,
'C' => 1,
'A' => 5,
'B' => 8,
);
@sorted_key = sort { $a cmp $b } keys %hash; # ハッシュをキーの昇順にソート
foreach $aKey(@sorted_key) {
print "[$aKey]:$hash{$aKey}\n";
}
結果は以下のようになります。
[A]:5
[B]:8
[C]:1
[D]:4
[E]:9
注意が必要なのは、連想配列自体に順序があるわけではないので、連想配列の中身の順序が変わるわけではないということです。
ソートするのはあくまでもキーについてだけです。
%hash = (
'D' => 4,
'E' => 9,
'C' => 1,
'A' => 5,
'B' => 8,
);
@sorted_key = sort { $a cmp $b } keys %hash; # ハッシュをキーの昇順にソート
foreach $aKey(@sorted_key) {
print "[$aKey]:$hash{$aKey}\n";
}
結果は以下のようになります。
[A]:5
[B]:8
[C]:1
[D]:4
[E]:9
注意が必要なのは、連想配列自体に順序があるわけではないので、連想配列の中身の順序が変わるわけではないということです。
ソートするのはあくまでもキーについてだけです。
配列に配列を挿入する
配列に配列を挿入するには、spliceを使います。
my @foo = qw(ari hituji inko cat dog);
my @baa = qw(sky tree note memo);
splice(@foo, 1, 0, @baa); # 配列fooの1番目に配列baaを挿入
my $i = 0;
foreach my $item(@foo) {
print "[$i]:$item\n";
$i++;
}
結果は以下のようになります。
[0]:ari
[1]:sky
[2]:tree
[3]:note
[4]:memo
[5]:hituji
[6]:inko
[7]:cat
[8]:dog
my @foo = qw(ari hituji inko cat dog);
my @baa = qw(sky tree note memo);
splice(@foo, 1, 0, @baa); # 配列fooの1番目に配列baaを挿入
my $i = 0;
foreach my $item(@foo) {
print "[$i]:$item\n";
$i++;
}
結果は以下のようになります。
[0]:ari
[1]:sky
[2]:tree
[3]:note
[4]:memo
[5]:hituji
[6]:inko
[7]:cat
[8]:dog
配列の要素を削除
配列の要素を削除するには、spliceを使います。
my @foo = qw(ari hituji inko cat dog);
splice(@foo, 2, 2); # 2番目の要素から2つ削除
my $i = 0;
foreach my $item(@foo) {
print "[$i]:$item\n";
$i++;
}
結果は以下のようになります。
[0]:ari
[1]:hituji
[2]:dog
my @foo = qw(ari hituji inko cat dog);
splice(@foo, 2, 2); # 2番目の要素から2つ削除
my $i = 0;
foreach my $item(@foo) {
print "[$i]:$item\n";
$i++;
}
結果は以下のようになります。
[0]:ari
[1]:hituji
[2]:dog
配列の全ての要素を加工する
配列の全ての要素を加工するには、mapを使います。
use utf8;
binmode STDIN, "utf8";
binmode STDOUT, "utf8";
my @foo = qw(ari hituji inko cat dog);
@hoge = map { my $hogehoge = $_."さん" } @foo;
my $i = 0;
foreach my $item(@hoge) {
print "[$i]:$item\n";
$i++;
}
結果は以下のようになります。
[0]:ariさん
[1]:hitujiさん
[2]:inkoさん
[3]:catさん
[4]:dogさん
use utf8;
binmode STDIN, "utf8";
binmode STDOUT, "utf8";
my @foo = qw(ari hituji inko cat dog);
@hoge = map { my $hogehoge = $_."さん" } @foo;
my $i = 0;
foreach my $item(@hoge) {
print "[$i]:$item\n";
$i++;
}
結果は以下のようになります。
[0]:ariさん
[1]:hitujiさん
[2]:inkoさん
[3]:catさん
[4]:dogさん
複数配列から重複しない行のみ抽出する
複数配列から重複しない行のみ抽出するには、以下のようにgrepを使います。
#!/opt/local/bin/perl
use utf8;
my @foo = qw(ari hituji inko cat dog);
my @baa = qw(cat ebi kuma hituji tora cat);
my %count;
$count{$_}++ for (@foo, @baa); # @fooと@baaの要素の数を数える
@hoge = grep { $count{$_} < 2 } keys %count; # 要素数が2より小さいもののみ抽出
my $i = 0;
foreach my $item(@hoge) {
print "[$i]:$item\n";
$i++;
}
結果は以下のようになります。
[0]:ari
[1]:inko
[2]:dog
[3]:ebi
[4]:kuma
[5]:tora
#!/opt/local/bin/perl
use utf8;
my @foo = qw(ari hituji inko cat dog);
my @baa = qw(cat ebi kuma hituji tora cat);
my %count;
$count{$_}++ for (@foo, @baa); # @fooと@baaの要素の数を数える
@hoge = grep { $count{$_} < 2 } keys %count; # 要素数が2より小さいもののみ抽出
my $i = 0;
foreach my $item(@hoge) {
print "[$i]:$item\n";
$i++;
}
結果は以下のようになります。
[0]:ari
[1]:inko
[2]:dog
[3]:ebi
[4]:kuma
[5]:tora
複数配列から重複行を抽出する
複数配列から重複行を取り出すには、grepを使うと便利です。
#!/opt/local/bin/perl
use utf8;
my @foo = qw(ari hituji inko cat dog);
my @baa = qw(cat ebi kuma hituji tora);
my %seen;
my $i = 0;
my @hoge = grep { ++$seen{$_} == 2 } (@foo, @baa);
foreach my $item(@hoge) {
print "[$i]:$item\n";
$i++;
}
結果は以下のようになります。
[0]:cat
[1]:hituji
1行目
Perlに限った話ではありませんが、ソースファイルの1行目には以下の様な記述をよく見かけます。
#!/opt/local/bin/perl
これはperl言語特有のものではなく、Linux等のシェルのお約束です。
上記の様に「#!」から始まる記述があることで、例えば普段はperlのプログラムを起動する時に、
perl hoge.pl
のように起動しますが、上記の記述があれば
hoge.pl
で起動できるようになります。(もちろん実行権限が付与されている必要があります。)
上の例では、シェルが実行権限の付いたhoge.plを開きますが、最初の行に「#!」から始まる行があることで、以降の/opt/local/bin/perlを起動し、その引数として自ファイルを渡してくれるようになります。
ですので、必ず
perl hoge.pl
等のように起動する人にとっては「#!」の行はいらないことになります。
ただし、他の人が同ファイルを起動しようとして
「hoge.pl」で起動できない!なんじゃこりゃ!?
と困ることがあるかもしれないので、お約束として付けておくのが習慣になっているようです。
ちなみに、「#!」の行は必ず1行目にある必要があります。2行めとかにあってもシェルは認識してくれません。
#!/opt/local/bin/perl
これはperl言語特有のものではなく、Linux等のシェルのお約束です。
上記の様に「#!」から始まる記述があることで、例えば普段はperlのプログラムを起動する時に、
perl hoge.pl
のように起動しますが、上記の記述があれば
hoge.pl
で起動できるようになります。(もちろん実行権限が付与されている必要があります。)
上の例では、シェルが実行権限の付いたhoge.plを開きますが、最初の行に「#!」から始まる行があることで、以降の/opt/local/bin/perlを起動し、その引数として自ファイルを渡してくれるようになります。
ですので、必ず
perl hoge.pl
等のように起動する人にとっては「#!」の行はいらないことになります。
ただし、他の人が同ファイルを起動しようとして
「hoge.pl」で起動できない!なんじゃこりゃ!?
と困ることがあるかもしれないので、お約束として付けておくのが習慣になっているようです。
ちなみに、「#!」の行は必ず1行目にある必要があります。2行めとかにあってもシェルは認識してくれません。
2013年3月6日水曜日
配列を任意の文字列で区切って表示する
joinを使えば配列を任意の文字列で区切って表示することができます。
@foo = qw(A B C D E F);
print join("\t", @foo)."\n"; # 配列をタブ区切りで表示
結果は以下のようになります。
A B C D E F
@foo = qw(A B C D E F);
print join("\t", @foo)."\n"; # 配列をタブ区切りで表示
結果は以下のようになります。
A B C D E F
配列をハッシュに変換する
配列を要素のキーを持つ連想配列(ハッシュ)にすることができます。
@foo = ('A', 'B', 'C');
# 配列を連想配列に変換
%hash = ();
$hash{$_} = 1 for @foo;
foreach $key(keys %hash) {
print "$key:$hash{$key}\n";
}
結果は以下のようになります。
A:1
C:1
B:1
@foo = ('A', 'B', 'C');
# 配列を連想配列に変換
%hash = ();
$hash{$_} = 1 for @foo;
foreach $key(keys %hash) {
print "$key:$hash{$key}\n";
}
結果は以下のようになります。
A:1
C:1
B:1
配列に要素が存在するかチェックする
配列に要素が存在するかチェックするには、foreachで1個づつチェックしても良いですが、以下のようにすればより短い行数ですみます。
grepを使用
@foo = ('A', 'B', 'C');
if (grep {$_ eq 'B'} @foo) {
print "exists\n";
}
Listを使用
use List::Util;
grepを使用
@foo = ('A', 'B', 'C');
if (grep {$_ eq 'B'} @foo) {
print "exists\n";
}
Listを使用
use List::Util;
@foo = ('A', 'B', 'C');
if (List::Util::first{$_ eq 'C'} @foo) {
print "exists\n";
}
2013年3月5日火曜日
戻り値に配列を渡す
Perlでは、戻り値に配列を返す場合、そのまま返却することができます。
#!/opt/local/bin/perl;
my @array = &getMyArray();
$i = 0;
foreach $ref(@array) {
print "[$i]:$ref\n";
$i++;
}
sub getMyArray {
my @array = ('A', 'B', 'C');
return @array;
}
結果は
[0]:A
[1]:B
[2]:C
と出力されます。
また、クラスを使う場合でもそのまま配列を返却することが可能です。
main.pl
#!/opt/local/bin/perl;
package main;
use utf8;
use TestSub;
use Clone qw(clone);
my @foo = ('A','B','C');
my $s = TestSub->new(\@foo);
@foo = ();
my @array = $s->getYourArray();
$i = 0;
foreach $ref(@array) {
print "[$i]:$ref\n";
$i++;
}
TestSub.pm
package TestSub;
use utf8;
use Clone qw(clone);
sub new {
$self = shift; # クラス名を取得します
$ref = shift; # 配列への参照を受け取ります
my $array = clone($ref); # 配列の参照をコピーします
my @array2 = (4, 5, 6); # もう1つ別のメンバ変数を作っています
my $data = { # メンバ変数を作っています
ref => $array,
ref2=> \@array2,
};
return bless $data, $self;
}
sub getYourArray {
my $self = shift;
my $result = $self->{ref2}; # メンバ変数から配列を取得
return @$result; # 配列を返却
}
1;
結果は
[0]:4
[1]:5
[2]:6
と出力されます。
#!/opt/local/bin/perl;
my @array = &getMyArray();
$i = 0;
foreach $ref(@array) {
print "[$i]:$ref\n";
$i++;
}
sub getMyArray {
my @array = ('A', 'B', 'C');
return @array;
}
結果は
[0]:A
[1]:B
[2]:C
と出力されます。
また、クラスを使う場合でもそのまま配列を返却することが可能です。
main.pl
#!/opt/local/bin/perl;
package main;
use utf8;
use TestSub;
use Clone qw(clone);
my @foo = ('A','B','C');
my $s = TestSub->new(\@foo);
@foo = ();
my @array = $s->getYourArray();
$i = 0;
foreach $ref(@array) {
print "[$i]:$ref\n";
$i++;
}
TestSub.pm
package TestSub;
use utf8;
use Clone qw(clone);
sub new {
$self = shift; # クラス名を取得します
$ref = shift; # 配列への参照を受け取ります
my $array = clone($ref); # 配列の参照をコピーします
my @array2 = (4, 5, 6); # もう1つ別のメンバ変数を作っています
my $data = { # メンバ変数を作っています
ref => $array,
ref2=> \@array2,
};
return bless $data, $self;
}
sub getYourArray {
my $self = shift;
my $result = $self->{ref2}; # メンバ変数から配列を取得
return @$result; # 配列を返却
}
1;
結果は
[0]:4
[1]:5
[2]:6
と出力されます。
クラスのコンストラクタに配列を渡す
クラスのコンストラクタに配列を渡すには、以下のようにします。
main.pl
#!/opt/local/bin/perl;
package main;
use utf8;
use TestSub;
use Clone qw(clone);
@foo = ('A','B','C'); # 配列を作って
my $s = TestSub->new(\@foo); # コンストラクタに渡します
@foo = ();
$s->hello();
TestSubクラスを生成して配列(foo)を渡しています。
その後、TestSubクラスのhelloメソッドを呼び出しています。
helloメソッドは受け取った配列を表示するようにしています。
呼ばれる側のソースは以下のようになります。
TestSub.pm
package TestSub;
use utf8;
use Clone qw(clone);
sub new {
$self = shift; # クラス名を取得します
$ref = shift; # 配列への参照を受け取ります
my $array = clone($ref); # 配列の中身をコピーします
my @array2 = (4, 5, 6); # もう1つ別のメンバ変数を作っています
my $data = { # メンバ変数を作っています
ref => $array, # 引数で渡された配列
ref2=> \@array2, # ついでにもう1つ配列
};
return bless $data, $self; # blessでメンバ変数とクラスを関連付けて返却
}
sub hello {
my $self = shift; # クラス名を取得します
my $test = $self->{ref}; # メンバ変数refを取得します
foreach my $ref(@$test) {
print "hello ref1:$ref\n";
}
my $test2 = $self->{ref2};
foreach my $ref(@$test2) {
print "hello ref2:$ref\n";
}
}
1;
ミソとしては、配列の参照を受け取るだけなので、コンストラクタ内でコピーしてあげないといけない点です。上記ではcloneを呼び出して配列をコピーしています。(もちろんCloneを使わずに愚直に1要素づつコピーしてもOKです。)
実行結果は以下のようになります。
hello ref1:A
hello ref1:B
hello ref1:C
hello ref2:4
hello ref2:5
hello ref2:6
main.pl
#!/opt/local/bin/perl;
package main;
use utf8;
use TestSub;
use Clone qw(clone);
@foo = ('A','B','C'); # 配列を作って
my $s = TestSub->new(\@foo); # コンストラクタに渡します
@foo = ();
$s->hello();
TestSubクラスを生成して配列(foo)を渡しています。
その後、TestSubクラスのhelloメソッドを呼び出しています。
helloメソッドは受け取った配列を表示するようにしています。
呼ばれる側のソースは以下のようになります。
TestSub.pm
package TestSub;
use utf8;
use Clone qw(clone);
sub new {
$self = shift; # クラス名を取得します
$ref = shift; # 配列への参照を受け取ります
my $array = clone($ref); # 配列の中身をコピーします
my @array2 = (4, 5, 6); # もう1つ別のメンバ変数を作っています
my $data = { # メンバ変数を作っています
ref => $array, # 引数で渡された配列
ref2=> \@array2, # ついでにもう1つ配列
};
return bless $data, $self; # blessでメンバ変数とクラスを関連付けて返却
}
sub hello {
my $self = shift; # クラス名を取得します
my $test = $self->{ref}; # メンバ変数refを取得します
foreach my $ref(@$test) {
print "hello ref1:$ref\n";
}
my $test2 = $self->{ref2};
foreach my $ref(@$test2) {
print "hello ref2:$ref\n";
}
}
1;
ミソとしては、配列の参照を受け取るだけなので、コンストラクタ内でコピーしてあげないといけない点です。上記ではcloneを呼び出して配列をコピーしています。(もちろんCloneを使わずに愚直に1要素づつコピーしてもOKです。)
実行結果は以下のようになります。
hello ref1:A
hello ref1:B
hello ref1:C
hello ref2:4
hello ref2:5
hello ref2:6
クラスを作る
Perlでクラスを実装するには、以下のようにpackageとuseを組み合わせます。
main.pl
#!/usr/opt/local/bin/perl;
package main;
use utf8;
use TestClass; # TestClassを使用する
$c = TestClass->new(); # TestClassを生成する
$c->hello();
呼び込むクラスのファイル名は・・・.pm(plではありません)とします。
TestClass.pm
package TestClass;
use utf8;
sub new {
my $self = shift; # Perlのお約束で引数の先頭は自動的にクラス名が入るので、shiftで取得します
my $member = { # メンバ変数を作ってます
mem1=>1,
mem2=>2,
mem3=>3,
};
return bless $member, $self; # blessでメンバ変数とクラスを関連付けたものを返却します
}
sub hello {
print "Hi! I'm TestClass.\n";
}
1; # パッケージの読み込み結果(1:成功)を返却する
呼び込まれる側のソースですが、package句でクラス名を宣言する他に、最後の行で「1;」を書いて置かなければならないのが忘れやすいので注意が必要です。
main.pl
#!/usr/opt/local/bin/perl;
package main;
use utf8;
use TestClass; # TestClassを使用する
$c = TestClass->new(); # TestClassを生成する
$c->hello();
呼び込むクラスのファイル名は・・・.pm(plではありません)とします。
TestClass.pm
package TestClass;
use utf8;
sub new {
my $self = shift; # Perlのお約束で引数の先頭は自動的にクラス名が入るので、shiftで取得します
my $member = { # メンバ変数を作ってます
mem1=>1,
mem2=>2,
mem3=>3,
};
return bless $member, $self; # blessでメンバ変数とクラスを関連付けたものを返却します
}
sub hello {
print "Hi! I'm TestClass.\n";
}
1; # パッケージの読み込み結果(1:成功)を返却する
呼び込まれる側のソースですが、package句でクラス名を宣言する他に、最後の行で「1;」を書いて置かなければならないのが忘れやすいので注意が必要です。
2013年3月4日月曜日
配列の参照を中身までコピーする
配列をコピーするには以下のように簡単に行えますが、
@foo = @bar;
配列の参照をコピーしたい場合は参照がコピーされるだけなので中身の値までコピーしてくれるわけではありません。
my @foo = ('A', 'B');
my @bar = \@foo; # 参照をコピーしても中身までコピーされるわけではない
@foo = (); # 参照元を初期化
foreach my $ref(@$bar) { # 参照元が初期化されているのでここでは何も出力されません
print "$ref\n";
}
配列の参照を中身も含めてコピー(deep copy)したい場合は、foreach等を使って愚直に要素を1個ずつコピーするか、またはCloneモジュールを使います。
use Clone qw(clone);
my @foo = ('A', 'B');
my $bar = clone(\@foo); # 参照を中身までコピーする
@foo = (); # 参照元を初期化
foreach my $ref(@$bar) { # 参照元を初期化してもOK
print "$ref\n";
}
結果は以下のようになります。
A
B
@foo = @bar;
配列の参照をコピーしたい場合は参照がコピーされるだけなので中身の値までコピーしてくれるわけではありません。
my @foo = ('A', 'B');
my @bar = \@foo; # 参照をコピーしても中身までコピーされるわけではない
@foo = (); # 参照元を初期化
foreach my $ref(@$bar) { # 参照元が初期化されているのでここでは何も出力されません
print "$ref\n";
}
配列の参照を中身も含めてコピー(deep copy)したい場合は、foreach等を使って愚直に要素を1個ずつコピーするか、またはCloneモジュールを使います。
use Clone qw(clone);
my @foo = ('A', 'B');
my $bar = clone(\@foo); # 参照を中身までコピーする
@foo = (); # 参照元を初期化
foreach my $ref(@$bar) { # 参照元を初期化してもOK
print "$ref\n";
}
結果は以下のようになります。
A
B
登録:
投稿 (Atom)