Translate

2012年4月9日月曜日

リファレンスのメモ

変数の前に\をつけることでその変数に対する参照(リファレンス)でやり取りが可能になる。
そして、参照情報から実際の値を取り出すには、各変数のファニー文字(スカラー⇒$,
配列⇒@, ハッシュ⇒%)をつけてあげれば元の変数のように扱うことができる。

サンプルコード
#!/usr/bin/perl                                                                         
use feature 'say';
use strict;
use warnings;
use utf8;
use File::Find;

binmode STDIN,  ":utf8";
binmode STDOUT, ":utf8";

#配列、ハッシュ                                                                         
my @array = ("a", "b", "c");
my %hash  = (
             guu   => "rock",
             cyoki => "scissors",
             paa   => "paper",
            );

#リファレンス                                                                           
my $ref_array = \@array;
my $ref_hash  = \%hash;

                                                                                   
#表示                                                                                   
for(my $i = 0; $i < @{$ref_array}; $i++){
  say "${$ref_array}[$i]";
}


for my $key (keys %{$ref_hash}){ 
  say "key: $key / value: ${$ref_hash}{$key}";
}
実行結果:
a
b
c
key: paa / value: paper
key: cyoki / value: scissors
key: guu / value: rock
変数の頭に\をつけることをリファレンスと呼びその逆の行為をデリファレンスと呼ぶ。
デリファレンスした後
配列の場合 ${$ref_array}[$i]
ハッシュの場合 ${$ref_hash}{$key}
とアクセスすることもできるが、アロー演算子による表記が用意されているので
以下のように書き換えることができる。

配列の場合   $ref_array->[$i]
ハッシュの場合 $ref_hash->{$key}
サブルーチンの場合も同様にアロー演算子による表記が可能である。
まとめ。
配列   リファレンス->[要素]
ハッシュ リファレンス->{キー}
関数   リファレンス->(引数)


上記の例では、配列とハッシュの変数に格納してからリファレンスを
扱っているが直接リファレンスを扱うこともできる。

配列の場合
(要素, 要素, 要素)から
[要素, 要素, 要素]に変えるだけ。

ハッシュの場合
(キー=>値, キー=>値)から
{キー=>値, キー=>値}に変えるだけ。

上記の例を書き直すとこうなる。
#!/usr/bin/perl                                                                         
use feature 'say';
use strict;
use warnings;
use utf8;
use File::Find;

binmode STDIN,  ":utf8";
binmode STDOUT, ":utf8";


#リファレンス                                                                           
my $ref_array = ["a", "b", "c"];
my $ref_hash  = {
                 guu   => "rock",
                 cyoki => "scissors",
                 paa   => "paper",
                };

                                                                                   
#表示                                                                                   
for(my $i = 0; $i < @{$ref_array}; $i++){
  say "${$ref_array}[$i]";
}


for my $key (keys %{$ref_hash}){ 
  say "key: $key / value: ${$ref_hash}{$key}";
}
簡単ですね! さて、今度は多次元配列を表現してみます。
#!/usr/bin/perl                                                                         
use feature 'say';
use strict;
use warnings;
use utf8;
use File::Find;

binmode STDIN,  ":utf8";
binmode STDOUT, ":utf8";


#リファレンス
my $ref_array = [
                 [1, 2],
                 [3, 4, 5],
                 [6, 7, 8, 9, 0],
                ];


for (my $x = 0; $x < @{$ref_array}; $x++){
  for (my $y = 0; $y < @{$ref_array->[$x]}; $y++){
    say $ref_array->[$x][$y];
  }
}

@{$ref_array} で [1, 2]と[3, 4, 5]と[6, 7, 8, 9, 0]の3要素であることを取得し
@{$ref_array->[$x]}で各要素
[1, 2] => 2要素
[3, 4, 5] => 3要素
[6, 7, 8, 9, 0] => 4要素
であることを取得しています。

2012年4月8日日曜日

File::Find

■再帰的にディレクトリを移動して、ファイル/ディレクトリ名を取得する

.
├── 1
│   └── 2
│       └── 3.txt
├── a
│   └── b.txt
└── Sample.pl

上記構成を例に使用してみる。
■"1"ディレクトリの構成を調べる
#!/usr/bin/perl
use feature 'say';
use strict;
use warnings;
use utf8;
use File::Find;


find(\&wanted, '1');                                                                    

sub wanted{
  say "CurrentDirectory :", $File::Find::dir;
  say "Name             :", $_;
  say "FullPath         :", $File::Find::name;
  say "---";
}

実行結果:
CurrentDirectory :1
Name             :.
FullPath         :1
---
CurrentDirectory :1
Name             :2
FullPath         :1/2
---
CurrentDirectory :1/2
Name             :3.txt
FullPath         :1/2/3.txt
---



■複数のディレクトリを指定してみる
#!/usr/bin/perl
use feature 'say';
use strict;
use warnings;
use utf8;
use File::Find;


find(\&wanted, qw/1 a/); #配列で指定

sub wanted{
  say "CurrentDirectory :", $File::Find::dir;
  say "Name             :", $_;
  say "FullPath         :", $File::Find::name;
  say "---";
}

実行結果:
CurrentDirectory :1
Name             :.
FullPath         :1
---
CurrentDirectory :1
Name             :2
FullPath         :1/2
---
CurrentDirectory :1/2
Name             :3.txt
FullPath         :1/2/3.txt
---
CurrentDirectory :a
Name             :.
FullPath         :a
---
CurrentDirectory :a
Name             :b.txt
FullPath         :a/b.txt
---



■一番下の階層からスタートする
#!/usr/bin/perl
use feature 'say';
use strict;
use warnings;
use utf8;
use File::Find;


finddepth(\&wanted, '1');

sub wanted{
  say "CurrentDirectory :", $File::Find::dir;
  say "Name             :", $_;
  say "FullPath         :", $File::Find::name;
  say "---";
}

実行結果:
CurrentDirectory :1/2
Name             :3.txt
FullPath         :1/2/3.txt
---
CurrentDirectory :1
Name             :2
FullPath         :1/2
---
CurrentDirectory :1
Name             :.
FullPath         :1
---

FindBin

実行スクリプトのディレクトリを取得するモジュール

#!/usr/bin/perl
use feature 'say';
use strict;
use warnings;
use utf8;
use FindBin;
                                                        
say $FindBin::Bin;

libモジュールのパス指定をする際に利用すると便利。
use lib "$FindBin::Bin/lib";