Translate

2008年8月24日日曜日

File::Pathモジュール

ディレクトリを追加したり(mkdir関数)、ディレクトリを削除(rmdir関数)
していてふと思ったのだけど、rmdir関数だとディレクトリの中身が
空じゃないと削除してくれないんですね。

そんなわけで、削除したいディレクトリにファイルがある場合は
ディレクトリ内を削除してからフォルダを削除しないといけない
わけですが、非常にめんどい。
てか、車輪が標準装備されてるんだから使いましょう。
って話。

という流れで登場するのが、File::Pathモジュール。
やってくれることは、階層を持ったディレクトリの作成や
rm -rfコマンドのごとく指定したディレクトリにファイルが
あってもモジュール側で削除してくれます。

で、CPANに飛んでいきまずは、SYNOPSISをコピペで動かしみよう~
File::Path(Ver 2.04)

と、思ったらうまくいかないのですよ…
で、よくよく見たらmodernとtraditionalに別れてるわけで
自分のPCや、レンタル鯖のFile::Pathのバージョンを調べてみると
Ver1.08なわけです。
で、ひょっとしてってことで
perldoc -m File::Path
で、Ver1.08のPODを眺めてみるとサポートしてるのは、
Ver2.04で書いてあったtraditionalの方の書き方だったので
ひとまず、そちらで書いたら動いてくれました。


という前置きをしてから。
カレントディレクトリに./a/b/cと言ったディレクトリを作りたければ
use strict;
use warnings;
use File::Path;

#modern
mkpath( './a/b/c', {verbose => 0, mode => 0755} );

#traditional
mkpath( ['./a/b/c'], 0, 0755)

(※modernをサポートしてるかは、各自確認してみてください。)

引数についてですが、
2番目の引数をtrueになるように何か与えると
生成したフォルダの情報を吐き出します。
↓こんな感じ
mkdir ./a
mkdir ./a/b
mkdir ./a/b/c

勿論、既にフォルダが存在していた場合は何もしません。

3番目の引数は、パーミッションの設定です。
何もセットしない場合は、ディフォルトで0777がセットされるようです。


削除に関しても同じです。
カレントディレクトリに./a/b/cという構成のディレクトリがあったとして…
use strict;
use warnings;
use File::Path;

#modern
rmtree( './a' );

#traditional
rmtree( ['./a'] )


これで、削除ができますね。

おまけ。
winで、ppmから最新のFile::Pathを探してみたのだけど
最新を含んだリポジトリが見当たらなかったんで、
perl -MCPAN -e shell で
install File::Path で
さっくり入ってくれました。
ver2.04だと他にも引数が用意されていますね。

2008年8月21日木曜日

シュウォーツ変換!

前回、シュウォーツ変換を勉強した際の記事を下記にて覚え書きしました。
れっつ、そーと。

で、その続きです。
前回のシュウォーツ変換では、ソートで使った値に重複がありませんでした。
もし、テストの得点順に並び替えるなんて時を考えた場合にある科目では
同じ点数の人がいたので、別の科目もつかって並び替えをしようとした場合を
考えてみます。

Excelで見たらどういうことかわかりよいですかねぇ??
ExcelでB列に名前、C列に国語の点数、D列に算数の点数が入っていたとします。
点数は、下の図の通りです。



それで、国語の点数で高い順に並び変えようと思ったのですが
tarou と jirou、saburou と shirouが同じ得点だったので
算数の得点も使って高得点な順に並び変えることにしました。
↓つまりこういうこと。



これを実行すると、下記のようになりますよね。



これをシュウォーツ変換を使ってやってみます。
use strict;
use warnings;

my %score = (
tarou => {
kokugo => 90,
sansuu => 10,
},
jirou => {
kokugo => 90,
sansuu => 50,
},
saburou => {
kokugo => 10,
sansuu => 10,
},
shirou => {
kokugo => 10,
sansuu => 90,
},
);

my @person = qw(tarou jirou saburou shirou);
my @ranking = map { $_->[0] }
sort { $b->[1] <=> $a->[1] || $b->[2] <=> $a->[2] }
map { [$_, $score{$_}{'kokugo'}, $score{$_}{'sansuu'} ]}
@person;

print "@ranking\n";


こんな感じになって実行すると…
jirou tarou shirou saburou
になります。

つまり、map-sort-mapのうち最後のmapでは、
map { ['並び替えたい物', '値1', '値2', ・・・, '値N'] }
としてあげればよくて
スペースシップ演算子では、左右で同じ値だと0を返すので
or演算子で同じ値だったら次の条件を使って判断してもらう
ようにすれば、いくらでも条件を追加していくことができます。
sort{ $b->[1] <=> $a->[1] || $b->[2] <=> $a->[2] || … $b->[N] <=> $a->[N] }
最初のmapはリファレンスの最初の要素を拾っているだけなので変わりません。
便利よいですね。

以上

2008年8月17日日曜日

Instant.js

0.Instant.jsって
画像をフォトフレームに入れて表示したように見せることができます。
フレームの色や傾きなど指定できます。

1.download
http://www.netzgesta.de/instant/
内の下の方に移動するとDowloadという折りたたみ式のメニュー
があるのでクリックするとリンクが出てきます。

(なにげに、一番上のinstant.jsってロゴをクリックしてもダウンロードできますねぇ。)

2.使い方
ファイル構成が下記の場合で説明します。
index.html
┣ js
┃ ┗ instant.js
┗ pic
┣ image-1.jpg
┣ image-2.jpg
┣ image-3.jpg
┣ image-4.jpg
┣ image-5.jpg
┗ image-6.jpg

まず、javascriptのファイルを指定をします。
<script type="text/javascript" src="./js/instant.js"></script>

あとは、imgタグに class="instant" を追加するだけです。
例)
<img src="http://www.blogger.com/pic/image-1.jpg" class="instant" />
<img src="http://www.blogger.com/pic/image-2.jpg" class="instant" />
<img src="http://www.blogger.com/pic/image-3.jpg" class="instant" />

デフォルトだと、フレームが白で傾きが
左下がり、平行、右下がりの繰り返しになります。



ちなみに、class名を変えることで下記の効果が得られます。
◇傾き
"instant" → "instant itiltnone" ⇒ 画像を傾けない。
"instant" → "instant itiltleft" ⇒ 左下がり
"instant" → "instant itiltright" ⇒ 右下がり

◇写真フレームの影
下記のようにshadowの後に0(薄い)~100(濃い)を
追加することで写真フレームの影の濃さを変更できます。
"instant" → "instant ishadow50"

◇フォトフレームの色
下記のようにicolorの後に色を指定することで
フォトフレームの色を変えることができます。
"instant" → "instant icolor1038C6"

上の3つを混合し、全て右上がりでフレームカラーを
googleちっくにして一番左だけ影を濃くするにはこんな
コードになります。
<img src="http://www.blogger.com/pic/image-1.jpg"
class="instant itiltleft ishadow100 icolor1038C6" />
<img src="http://www.blogger.com/pic/image-2.jpg" class="instant itiltleft icolorCE1800" />
<img src="http://www.blogger.com/pic/image-3.jpg" class="instant itiltleft icolorFFCF00" />
<img src="http://www.blogger.com/pic/image-4.jpg"
class="instant itiltleft ishadow100 icolor1038C6" />
<img src="http://www.blogger.com/pic/image-5.jpg" class="instant itiltleft icolor4ACB4A" />
<img src="http://www.blogger.com/pic/image-6.jpg" class="instant itiltleft icolorCE1800" />




3.参考サイト
ゼロからはじめるInstant.js - Webの画像を壁掛け写真風にアレンジ

4.instant.jsのサイト
http://www.netzgesta.de/instant/

2008年8月15日金曜日

Image::Magickモジュール

いろいろいじってみます。
ひとまず、ファイルの構成は下記の通りで進めます。
-----ファイル構成-----
t.pl
┗ pic
  ┗ b001.bmp
----------------------

◆画像のサイズを調べてみます。
use strict;
use warnings;
use Image::Magick;

my $picture = "./pic/b001.bmp";

my $img = Image::Magick->new();
$img->Read($picture);
my ($x, $y) = $img->Get('width', 'height');
print "Size:$x×$y\n";


実行結果
----------------------
Size:333×272
----------------------


◆縦/横比を保ったまま、100pxの正方形に収まるようにリサイズ変更する。
(縦/横のうち長い方を指定したサイズに変更し、縦横比に従い短い方を自動的に変更する方法)
use strict;
use warnings;
use Image::Magick;

my $old_pic = "./pic/b001.bmp";
my $new_pic = "./pic/new_b001.bmp";

my $img = Image::Magick->new();
$img->Read($old_pic);
my ($x, $y) = $img->Get('width', 'height');
print "Old_Size:$x x $y\n";

$img->Resize(geometry => 100);
$img->Write($new_pic);
$img->Read($new_pic);
($x, $y) = $img->Get('width', 'height');
print "New_Size:$x x $y\n";


実行結果
-------------------------------------------
Old_Size:333×272
New_Size:100×82
-------------------------------------------
これで、picフォルダ内に、new_b001.bmpが
100×82の画像が作成されます。


ちなみに、画像じゃないデータを渡すと何もおきません。
(※今後少しずつ追記していきます。)
Image::Magickの使い方→http://www.imagemagick.org/script/perl-magick.php

2008年8月14日木曜日

File::Findモジュール

あるディレクリ内のファイルを再帰的に探し出したい!
という時に使えるモジュールですね。

今回のコードはこんな環境で使ったとします。

test.pl
┗ etc
 ┗ h001.html
  ┣ pic
  ┃ ┗ g001.gif
  ┃
  ┗ file
   ┣ c001.css
   ┗ j001.js

use strict;
use warnings;
use File::Find;

my $directory = "./etc"; #./etcをスタートしてその配下を探索。
find(\&output, $directory); #ファイルorフォルダを見つけるたびに\&outputを参照。

sub output{
print "\$File::Find::dir : $File::Find::dir\n";
print "\$_ : $_\n";
print "\$File::Find::name : $File::Find::name\n\n";
}


実行結果
---------------------------------------
$File::Find::dir : ./etc
$_ : .
$File::Find::name : ./etc

$File::Find::dir : ./etc
$_ : file
$File::Find::name : ./etc/file

$File::Find::dir : ./etc/file
$_ : c001.css
$File::Find::name : ./etc/file/c001.css

$File::Find::dir : ./etc/file
$_ : j001.js
$File::Find::name : ./etc/file/j001.js

$File::Find::dir : ./etc
$_ : pic
$File::Find::name : ./etc/pic

$File::Find::dir : ./etc/pic
$_ : g001.gif
$File::Find::name : ./etc/pic/g001.gif

---------------------------------------
見ての通りなんですが
$File::Find::dirで起点からのパスが格納されます。
$_は、ファイル名orフォルダ名が格納されます。
$File::Find::nameで起点からのパス + (ファイル名|フォルダ名)となってます。

2008年8月12日火曜日

Dumpvalueモジュール

前回投稿したData::Dumperモジュールに引き続き
データ構造見るならデバッガのxコマンドで吐出す形式と
同じ方がいいなぁーという場合には、
use strict;
use warnings;
use Dumpvalue;

my $d = Dumpvalue->new();
my %hash;
$hash{a}{b} = "ab";
$hash{a}{c} = "ac";
$hash{b}{a} = "ba";
$hash{b}{c} = "bc";
$hash{c}{a} = "ca";
$hash{c}{b} = "cb";
$d->dumpValue(\%hash);

実行結果
'a' => HASH(0x276224)
'b' => 'ab'
'c' => 'ac'
'b' => HASH(0x27605c)
'a' => 'ba'
'c' => 'bc'
'c' => HASH(0x1853ef0)
'a' => 'ca'
'b' => 'cb'


例えば、大量に続くコードの途中にある変数の構造が知りたい時に
標準出力してしまうよりファイルに出力した方が何かと便利よさそうですよね。
『PERL HACKS』が言うには、
dumpValue()の出力先が標準出力であることを利用して
select関数を使って標準出力を一時的に変更してあげれば
ファイルへ出力もOKになるってことで…
use strict;
use warnings;
use Dumpvalue;

my $d = Dumpvalue->new();
my %hash;
$hash{a}{b} = "ab";
$hash{a}{c} = "ac";
$hash{b}{a} = "ba";
$hash{b}{c} = "bc";
$hash{c}{a} = "ca";
$hash{c}{b} = "cb";

open my $temp_fh, '>dump.txt';
my $old_fh = select($temp_fh); #select関数は、標準出力を変更し、現在の標準出力を返す。
$d->dumpValue(\%hash);
close $temp_fh;
select($old_fh); #標準出力を$old_fh(main::STDOUT)に戻す

で、ファイルに出力できますね。

Data::Dumperモジュール

リファレンスなどを含んでたり、構造が深くなっていくと
パットそれがどんな構造なのかわからなかったり、
あるモジュールの返す値ってどんな構造なんだ??
というときがあります。
そういう時に便利よいのがData::Dumperモジュールだそうです。
というわけで、使ってみる。

use strict;
use warnings;
use Data::Dumper;

my @array = ([qw(a b c)], [qw(d e f)], [qw(g h i)]);
print Dumper \@array; #リファレンスを渡す

実行結果
$VAR1 = [
[
'a',
'b',
'c',
],
[
'd',
'e',
'f',
],
[
'g',
'h',
'i',
],
];
わかりよいですねぇー。
他にも試してみますよー。
use strict;
use warnings;
use Data::Dumper;

my %hash;
$hash{a}{b} = "ab";
$hash{a}{c} = "ac";
$hash{b}{a} = "ba";
$hash{b}{c} = "bc";
$hash{c}{a} = "ca";
$hash{c}{b} = "cb";
print Dumper \%hash; #リファレンスを渡す
実行してみると…

$VAR1 = {
'c' => {
'a' => 'ca',
'b' => 'cb'
},
'a' => {
'c' => 'ac',
'b' => 'ab'
},
'b' => {
'c' => 'bc',
'a' => 'ba'
}
};
ちなみに、Data::Dumperにはオプションがあります。
Indent...インデントを変更。下記値を指定するとOK。
0→インデントなし
1→固定幅
2→自動可変(ディフォルト)

Terse...変数名の表示/省略
0→変数名を省略しない(ディフォルト)
1→可能であれば省略

Sortkeys...項目のソート
0→キーをソートしない(ディフォルト)
1→キーをソートする


例えば、インデント固定幅(1) 変数名なし(0)でキーでソートする(1)ように指定すると…
use strict;
use warnings;
use Data::Dumper;

my %hash;
$hash{a}{b} = "ab";
$hash{a}{c} = "ac";
$hash{b}{a} = "ba";
$hash{b}{c} = "bc";
$hash{c}{a} = "ca";
$hash{c}{b} = "cb";
local $Data::Dumper::Indent = 1;
local $Data::Dumper::Terse = 1;
local $Data::Dumper::Sortkeys = 1;
print Dumper \%hash; #リファ(ry
実行結果
{
'a' => {
'b' => 'ab',
'c' => 'ac'
},
'b' => {
'a' => 'ba',
'c' => 'bc'
},
'c' => {
'a' => 'ca',
'b' => 'cb'
}
}

Date::Dumperの和訳みっけましたので、メモ書きしときます。
Data::Dumper - perlデータ構造の出力/eval両用文字列化

関連→Dumpvalueモジュール