2011/02/16(水)[Perl] 覚書

ちょこっとメモ

記事として伸ばすかどうか判らないけれど、自分用メモ。

XML fileを扱う

use XML::Simpleとか使うと便利。HASH, ARRAYの接続に注意。Dumperで眺めてみるとわかりよい。


実行時型判定

refを使う。ref(変数)として、文字列が得られる。('ARRAY','HASH','REF','SCALAR'など。)

HASHの中身が入っているか確認する

if (!%hash_var) {
  print "cleared hash\n";
}
else {
  print keys %hash_var ;
}

参考

Perl 開発者のための XML: 第 1 回 XML と Perl -- 魔法の組み合わせ

2010/02/04(木)[Perl] 変数の型を調べる

変数の型を調べたい

ref演算子が使える模様。リファレンスならその型を返してくれる模様。リファレンスじゃなかったらnullぽ...

blessされているときは、クラス名が返ってくるらすぃ。い万ところ使わないから参考程度にメモ。

ソース

use strict ;

my $test ;
my $ref_1 = [1, 2] ;
my $ref_2 = \$test ;
my $ref_3 = $ref_1 ;
my $ref_4 = {1 =>'t'} ;
my %hash_1 = {1 =>'t', [2,3]} ;

	&chk_type($test) ;
	&chk_type($ref_1) ;
	&chk_type($ref_2) ;
	&chk_type($ref_3) ;
	&chk_type($ref_4) ;
	&chk_type(%hash_1) ;
	&chk_type(\%hash_1) ;

exit ;

sub chk_type($)
{
my $v = shift @_ ;
my $a = ref $v;
  print "$a へのリファレンス\n" if ($a) ;
  print "scaler\n" unless ($a) ;

}

実行結果

scaler
ARRAY へのリファレンス
SCALAR へのリファレンス
ARRAY へのリファレンス
HASH へのリファレンス
scaler
HASH へのリファレンス

配列やハッシュの要素として、任意の型をガンガン放り込めるので、それを調べて処理したいという欲求があったのですよ...

Cで書くなら、voidポインタをキャストして使っていたかなぁ。

C++やC#なら実行時型とか使って、同じような処理ができると思う。が、まぁ、今回はPerlだけ。ワンタイムの使い捨てになりかねないので..(^^;

2009/08/25(火)[perl] 多次元ハッシュ・配列~例示は何とやらの試金石

一次元

#!/usr/bin/perl -W

use strict ;

our %hash ;
our @hash ;

print \%hash . "\n" ;
print \@hash . "\n\n" ;


print " no-let: " . (exists($hash{hoge})?'true':'false') . "\n";


$hash{hoge} = ();
print " = (): " . ((exists($hash{hoge})?'true':'false')?'true':'false') . "\n";
print ref( $hash{hoge}) . "\n";
print \$hash{hoge} . "\n\n";

$hash{hoge} = [];
print " = []: " . ((exists($hash{hoge})?'true':'false')?'true':'false') . "\n";
print ref( $hash{hoge}) . "\n";
print \$hash{hoge} . "\n";
print $hash{hoge} . "\n\n";

$hash{hoge} = {};
print " = {}: " . (exists($hash{hoge})?'true':'false') . "\n";
print ref ($hash{hoge}) . "\n";
print \$hash{hoge} . "\n";
print ${\$hash{hoge}} . "\n\n";

$hash{hoge} = 1;
print " = 1: " . (exists($hash{hoge})?'true':'false') . "\n";
print ref( $hash{hoge}) . "\n";
print \$hash{hoge} . "\n\n";

出力例(環境や実行時により、値が異なる)


HASH(0x2e7214)
ARRAY(0x2e7204)

 no-let: false
 = (): true

SCALAR(0x1f81f4)

 = []: true
ARRAY
REF(0x1f81f4)
ARRAY(0x1f8294)

 = {}: true
HASH
REF(0x1f81f4)
HASH(0x1f82e4)

 = 1: true

SCALAR(0x1f81f4)

arrayの代入は、SCALARになるのか...


二次元(HASHにHASHを入れる)

#!/usr/bin/perl -W

use strict ;
use warnings ;
our %hash ;


print exists($hash{hoge});

# $hash{hoge} = {} ;
print $hash{hoge} . "\n" ; # ここで未初期化変数と文字列の結合でwarningが出る.
$hash{hoge}{foo} = 2 ;
$hash{hoge}{bar} = 44 ;
print $hash{hoge} . "\n" ;
print $hash{hoge}{foo} . "\n" ;    #これと
print $hash{hoge}->{foo} . "\n" ;  #これは 同意らしい.
print ${$hash{hoge}}{foo} . "\n" ;   # $hash{hoge}が hash referenceなので${}で デリファレンスして {}でハッシュ値をとってくる.という解釈で.
print (keys %{$hash{hoge}}) . "\n" ; # 装飾子みたいなもんかな..
#print (keys $hash{hoge}) . "\n" ;   # NG

出力例。

HASH(0x18881f4)
HASH(0x18881f4)
2
2
2
barfoo

perlreftut from Active Perl 5.10

説明資料があった…

Arrow Rule In between two subscripts, the arrow is optional.

Instead of $a[1]->[2], we can write $a[1][2]; it means the same thing. Instead of $a[0]->[1] = 23, we can write $a[0][1] = 23; it means the same thing.

Now it really looks like two-dimensional arrays!

You can see why the arrows are important. Without them, we would have had to write $$a[1][2] instead of $a[1][2]. For three-dimensional arrays, they let us write $x[2][3][5] instead of the unreadable $${$x[2][3]}[5].

無名配列、無名ハッシュを作る手段は2つしかなくて、(''と'')でハッシュのリファレンスを、('['と']')で無名配列のリファレンスを作る。


ハッシュと配列の混在例

以上を踏まえて、少し確認する。

#$hash{hoge} = () ; # case A
#$hash{hoge} = [] ; # case B
# case C

print $hash{hoge} . "\n" ;
$hash{hoge}[0] = {foo=>1};  # 要素0 へ 無名ハッシュのリファレンスを代入(fooをもつハッシュはどこかで作られる)
$hash{hoge}[1] = {bar=>3};  # 同様.
print $hash{hoge} . "\n" ;       # これは配列のリファレンス値を返すはず。

print $hash{hoge}[0] . "\n" ;    # この三つは同じ。ハッシュのリファレンス値を返す。
print ${$hash{hoge}}[0] . "\n" ; # 
print $hash{hoge}->[0] . "\n" ;  # 
  • case C\明示的に初期化しない場合。\perlさんが勝手に用意してくれました(Warningが出る)
  • case A\case Cと同様でした。初期化したことにもならない。
  • case B\配列リファレンスがセットされ、要素を追加してもリファレンス値が変わらず。

んー、なにやっても同じか。\warningを出さないように、明示的にカラの配列リファレンスを放り込んでおくのが無難かな。

では、なぜ、挙動が変わったのだろうか。ほかのところでいらんことしていたのかもしれないなぁ... 持ち帰れないのが悔やまれる('A`

[Perl] 基礎的な事項

2009/06/13Perl::基礎import

[Perl] 簡単な文法メモ

スカラー変数

汎用変数と思えばいいかな. 型定義は特に無い.(値/文字列/リファレンス(ポインタ))

my $hogehoge

初期化しない状態は未定義(undef)となります。値ならゼロ、文字列ならNULL扱いになります。演算時に評価されますが、use warningすると未初期化変数の演算といわれます。undefかどうかの判定は、下記の関数を利用することになります。

defined($hogehoge)

下記の比較演算子は使えません。

$hogehoge == undef $hogehoge eq undef

scope hogehoge;

スコープ'hogehoge'を定義する。

require Exporter;

@ISA, @classname::ISA = @qw(the_class):

SuperClassを定義します. this class IS-A the_class.もしくは、下記のように記述できます。

use the_class;
@thisclass::ISA = qw(the_class);
||>
↓
>||
use base qw(the_class);

配列操作

初期化
@hoge = ('hoge','hogehoge',...);
@hoge = ("hoge","hogehoge",...); ← 展開される
@hoge = qw ( hoge hogehoge ...); ← 展開される. 空白で区切られる.
参照
$hoge[0] # zero-origin
$#hoge   # indexの末尾が得られる
$hoge[-1] <=> $hoge[$#hoge]

ハッシュ操作

宣言

my %hash_name;
初期化
%hash = ( "key1" => value, "key2" => value);
または、一次元配列でkey,valueの順列。
%hash = (key1, value1, key2, value2)
%hash = (); # 空っぽになる. |ハッシュアクセス:
keys %hash # hashの持つキーを配列で取得する.
values %hash # 同, 値を配列で取得する.
exists $hash{'key'}; # そのキーが存在するか. 真/偽を返す. 未初期化と定義済みと判断可能.
delete $hash{key} # 指定したキー/値を削除する.

pack/unpack

syntax:

pack TEMPLATE, LIST
unpack TEMPLATE, LIST

templateの書式を以下に示します。

フォーマット 意味 フォーマット 意味
aASCII 文字列AASCII 文字列、足りない領域はスペース文字で埋める
bビット列 (昇ビット順)Bビット列 (降ビット順)
c符号付き char 値C符号なし char 値
d機種依存の倍精度浮動小数点数f機種依存の単精度浮動小数点数
h16進数文字列 (下位ビットが先)H16進数文字列 (上位ビットが先)
i符号付き int 値I符号なし int 値
l符号付き long 値L符号なし long 値
nネットワークバイト順序 (ビッグエンディアン) の short 値Nネットワークバイト順序 (ビッグエンディアン) の long 値
p文字列へのポインタP構造体 (固定長文字列) へのポインタ
s符号付き short 値S符号なし short 値
vVAXバイト 順序 (リトルエンディアン) の short 値VVAXバイト 順序 (リトルエンディアン) の long 値
uuuencode した文字列xヌル文字
X1バイト後退@絶対位置までヌル文字で埋める
  • フォーマット文字の後ろには、それを何回繰り返すかを示す数字COUNTを付けることができます。\COUNTに * を指定すると、残っているすべての要素を使います。
  • フォーマット文字(COUNTも含める)同士の間にはスペースを挟むことができます。
  • a、A、b、B、h、H以外のフォーマットは、第2引数LISTからCOUNTで指定された分の値を使います。
  • aやAというフォーマットに対してCOUNTを使うと、繰り返し数で示す長さの文字列となるように、\必要に応じてヌル文字かスペース文字を付け足します。
  • unpackするとき、Aは後続のスペース文字やヌル文字を取り除きますが、aはそのままにします。\同様に、bやBは、繰り返し数で示すビット長のビット列にパックします。
  • hやHは、そのニブル長のニブル列にパックします。
  • Pは、指定した長さの構造体へのポインタをパックします。
  • 実数 (floatとdouble) は、機種依存のフォーマットしかありません。\あるマシンで パックした浮動小数点数は、別のマシンでは読めない可能性があります。

split

区切り文字を指定して、stringを分割します。

@list = split(/\t/ , $var); // 区切りはTAB文字となっていることを見る.
@list = split(/[\t]/ , $var); // 区切りはTAB文字となっていることを見る.
 // 複数指定もできるが,区切り文字もリストに放り込まれる.

FileI/O

個人メモだから説明を端折ってもいいかな...\Cの標準関数 fopen/fclose みたいな感じで。出力は">"をつけて表す。

my @binhex;

 if ( ! open(fp, "<".$fname ) ) {
   printf("cannot open \"$fname\" \n");
   die ;
 }
 binmode( fp );
 while( read(fp, $buffer, $size_of_bytes) ){
   @binhex = unpack( "v32", $buffer ) ;        # divide little endian(short) x 32
 }


参考サイト

  • Smart Smartさん\非常にまとまっているサイト。Perl講座、HTML講座、JavaScript講座、SQL講座、注目技術・アクセス講座と幅広く展開されています。困った時は訪れるとよいかと思います。