実装関連事項

各種プログラミング言語の基本的な書き方やソフトウェア等の使用方法について.

Cpanmのインストール

モジュールを管理するためのソフトウェアである cpamn を $HOME/local/bin にインストールするには以下のようにする.最初にディレクトリを移動する.

$ cd $HOME/local/bin

次に以下のコマンドを打つ.これによって cpamn がダウンロードされる.

$ wget https://raw.github.com/miyagawa/cpanminus/master/cpanm

最後に,ファイルに実行権を与える.これでインストールが終了する.

$ chmod ugo+x cpamn

シェルに Bash を使っている場合は ~/.bashrc に以下の2行を追加する.最初の行の $HOME/local は cpanm がインストールしたモジュールを入れるためのディレクトリを作るところを指定する.2番目の行はモジュールのサーチパスを指定する記述であり,実際に Perl でモジュールを使用するときにここのパスに指定されたモジュールがあるかどうかが確認される.

export PERL_CPANM_OPT="--local-lib=$HOME/local"
export PERL5LIB=$HOME/local/lib/perl5:$PERL5LIB

モジュールサーチパスの確認

モジュールが格納されるパスは以下のコマンドを打つことで確認できる.

$ perl -e 'print "$_\n" foreach @INC'

モジュールのインストール方法

モジュールは,cpamn に引き続き,モジュール名を指定するだけで上記のパスにインストールされる.Cpanm を最初に使用する際は,上の PERL_CPANM_OPT で指定したディレクトリにモジュール格納用のディレクトリが生成される.インストールは以下のようにする.

$ cpanm Math::MatrixReal

エラーが出る場合は,-force を加えることでうまくいく場合がある.

$ cpanm -force Math::MatrixReal

インストールが成功したかどうかは以下のコマンドで確認できる.何も表示されなければ成功.

$ perl -MMath::MatrixReal -e 1

インストールされているモジュールのバージョンは以下のように打つことで確認できる.

$ perl -MMath::MatrixReal -le 'print $Math::MatrixReal::VERSION'

インストールモジュールの確認

インストール済みのモジュールは以下のコマンドを打つことで確認できる.環境によっては最後尾に -print を加える必要がある.

$ find `perl -e 'print "@INC"'` -name '*.pm'

モジュールサーチパスを明示的に指定してプログラムを実行

自身で設定したモジュールサーチパスではグリッドエンジンを使った際にエラーがでる場合がある.そのようなときには,-I オプションを使うことでモジュールサーチパスを明示的に指定することができる.

$ perl -I ~/local/perl5/lib/perl5 foo.pl

配列の基本操作

一度使用した配列を再び初期化して用いたいときは以下のように空の要素 '()' を代入することで行う.

#!/usr/bin/env perl
use strict;
use warnings;

MAIN:
{
	my @array=qw/1 2 3/;
	.
	.
	.
	@array=();
}

ハッシュも同様にリセットすることができる.

#!/usr/bin/env perl
use strict;
use warnings;

MAIN:
{
	my @hash=("a",1,"b",2,"c",3);
	.
	.
	.
	%hash=();
}

ハッシュのキーから配列を生成するには以下のようにする.

#!/usr/bin/env perl
use strict;
use warnings;

MAIN:
{
	@array=keys(%hash);
}

ハッシュの値から配列を生成するには以下のようにする.

#!/usr/bin/env perl
use strict;
use warnings;

MAIN:
{
	@array=values(%hash);
}

ある配列 @array からハッシュ %hash を生成するには以下のようにする.ハッシュのキーには配列の中身が,値には 1 が入る.

#!/usr/bin/env perl
use strict;
use warnings;

MAIN:
{
	my %hash=map{$_=>1}@array;
}

改行コードの削除

Perlに付属の改行を削除する関数 chomp では Windows から Linux にインポートしたファイル等の改行を削除できない場合がある.システムによって用いる改行コードが異なるため引き起こる.UNIX系では '\x0A' が、Windowsでは '\x0D\x0A' が改行コードとして割り当てられている.このようなシステムによる改行コードの違いを気にせずに改行コードを一気に削除するには以下のコードを用いる.

#!/usr/bin/env perl
use strict;
use warnings;

MAIN:
{
	$line=~s/\x0D\x0A$|\x0D$|\x0A$//;
}

ファイル等の存在確認

ファイルおよびディレクトリの存在確認には,それぞれ -f および -d を利用する.ファイルまたはディレクトリの存在チェックには -e を用いる.

#!/usr/bin/env perl
use strict;
use warnings;

MAIN:
{
	unless(-d "./hoge")
	{
		`mkdir hoge`;
	}
}

ディレクトリの移動

コード内でディレクトリを移動させるためにはモジュール Cwd を利用する.Bashでいうところの,pushd や popd を使うことができる.カレントディレクトリからディレクトリ foo に pushd で移動,さらにその下の階層の bar に移動後,カレントディレクトリに popd で戻るには以下のようにする。

#!/usr/bin/env perl
use strict;
use warnings;
use Cwd;

MAIN:
{
	my @dirs; # A list to store directory information
	
	# Move to directory, foo (pushd)
	push(@dirs,getcwd);
	chdir("foo");
	
	# Move to directory, bar (pushd)
	push(@dirs,getcwd);
	chdir("bar");
	
	# Go back to foo (popd)
	chdir(pop(@dirs));
	
	# Go back to the initial directory (popd)
	chdir(pop(@dirs));
}

モジュールを使用しない場合のコマンドライン引数の取得

モジュールを用いずにコマンドラインで指定した引数を取得するには以下のように書く.

#!/usr/bin/env perl
use strict;
use warnings;

MAIN:
{
	# Default value
	my $input="foo";
	my $param=50;
	my $output="bar";
	
	&parseArgument(@ARGV);
	
	# Body of the program
}
sub parseArgument
{
	my $arg;
	if(@ARGV==0)
	{
		&printUsage;
		exit();
	}
	while($arg = shift)
	{
		if		($arg eq "-i")	{ $input	= shift; }
		elsif	($arg eq "-p")	{ $param	= shift; }
		elsif	($arg eq "-o")	{ $output	= shift; }
	}
	
	(-e $input) || die "No input\n";
}
sub printUsage
{
    print STDERR <<"EOD";

 ====================================================
 Usage: sample.pl [options] -i input.fa -o output.txt
 ====================================================
 
 options
 -i  fasta file, required
 -p  parameter, optional
 -o  output file name, required

EOD
}

以上のコードを実行すると以下のような引数をとることができる.

$ hoge.pl -p 100 -i hoge.fa -o hoge.txt

環境変数の取り扱い

Perl で環境変数を扱うには $ENV{} という特殊な変数を利用する.環境変数 $PATH の中身を表示させたい場合は以下のように書く.

#!/usr/bin/env perl
use strict;
use warnings;

MAIN:
{
	print $ENV{"PATH"},"\n";
}

新たな環境変数 $TMPDIR を設定したい場合は以下のように書く.

#!/usr/bin/env perl
use strict;
use warnings;

MAIN:
{
	$ENV{"TMPDIR"}="/var/tmp";
}

$PATH に新たなディレクトリ ~/bin を追加したい場合は以下のように書く.

#!/usr/bin/env perl
use strict;
use warnings;

MAIN:
{
	$ENV{"PATH"}="$ENV{HOME}/bin:".$ENV{"PATH"};
}

書式付き出力

書式を指定して出力するためには printf() を利用する.

#!/usr/bin/env perl
use strict;
use warnings;

MAIN:
{
	printf("%s\n","foo");   # foo
	printf("%5s\n","foo");  # __foo
	printf("%-5s\n","foo"); # foo__
	
	printf("%d\n",100);     # 100
	printf("%5d\n",100);    # __100
	printf("%-5d\n",100);   # 100__
	printf("%05d\n",100);   # 00100
	
	printf("%f\n",3.14);    # 3.140000
	printf("%6.3f\n",3.14); # _3.140
}

複数行の出力

複数行を一度に出力するには以下のように書く."DOC" から DOC で囲まれた範囲がそのまま出力される.この文字列は DOC に限らず,TEXT でも HOGE でもなんでも良い.

#!/usr/bin/env perl
use strict;
use warnings;

MAIN:
{
	print STDOUT <<"DOC";
	
	 2nd line
	 foo
	 4th line
	
	DOC
}

これを実行すると以下のようになる.

 
 2nd line
 foo
 4th line
 

Math::Roundを使った四捨五入

四捨五入をする方法のひとつに Math::Round モジュールの関数 nearest() を使う方法がある.関数 nearest() では四捨五入する桁数を指定することができる.実際には,"nearest(四捨五入する桁数,対象の数値)" のように用いる.

#!/usr/bin/env perl
use strict;
use warnings;
use Math::Round;

MAIN:
{
	print nearest(0.01, 57.546),"\n";
	print nearest( 0.1, 57.546),"\n";
	print nearest(   1, 57.546),"\n";
	print nearest(  10, 57.546),"\n";
}

上のようなファイルを実行した結果は以下のようになる.

57.55
57.5
58
60

すなわち,四捨五入する桁数に,0.01を入力すると小数第三位が四捨五入,0.1を入力すると小数第二位が四捨五入,1を入力すると小数第一位が四捨五入,10を入力すると一の位が四捨五入される.

行列の扱い

Perl で行列を簡単に扱うには,モジュール Math::MatrixReal が使える.

MatrixReal では行列はスカラーとして扱われる (行列を代入する変数のシジルが $).以下のように書くと,多次元配列 @matrix から MatrixReal を使って行列 $matrix を生成できる.

#!/usr/bin/env perl
use strict;
use warnings;
use Math::MatrixReal;

MAIN:
{
	my @matrix;
	my $k=1;
	for(my $i=0;$i<3;$i++)
	{
		for(my $j=0;$j<3;$j++)
		{
			$matrix[$i][$j]=$k;
			$k++;
		}
	}
	my $matrix=Math::MatrixReal->new_from_rows(\@matrix);
	print $matrix;
}

この場合,3×3の生配列 @matrix から MatrixReal 配列 $matrix が生成される.これを実行すると以下のようになる.

[  1.000000000000E+00  4.000000000000E+00  9.000000000000E+00 ]
[  1.600000000000E+01  2.500000000000E+01  3.600000000000E+01 ]
[  4.900000000000E+01  6.400000000000E+01  8.100000000000E+01 ]

逆行列を作成するには以下のようにする.$matrix から $inverse を生成する.

#!/usr/bin/env perl
use strict;
use warnings;
use Math::MatrixReal;

MAIN:
{
	my @matrix;
	my $k=1;
	for(my $i=0;$i<3;$i++)
	{
		for(my $j=0;$j<3;$j++)
		{
			$matrix[$i][$j]=$k**2;
			$k++;
		}
	}
	my $matrix=Math::MatrixReal->new_from_rows(\@matrix);
	my $inverse=$matrix->inverse;
	print $inverse;
}

これを実行すると以下のようになる.

[  1.291666666667E+00 -1.166666666667E+00  3.750000000000E-01 ]
[ -2.166666666667E+00  1.666666666667E+00 -5.000000000000E-01 ]
[  9.305555555556E-01 -6.111111111111E-01  1.805555555556E-01 ]

行列の要素を取り出すときは element を使い,以下のようにする.

#!/usr/bin/perl
use strict;
use warnings;
use Math::MatrixReal;

MAIN:
{
	my @matrix;
	my $k=1;
	for(my $i=0;$i<3;$i++)
	{
		for(my $j=0;$j<3;$j++)
		{
			$matrix[$i][$j]=$k**2;
			$k++;
		}
	}
	my $matrix=Math::MatrixReal->new_from_rows(\@matrix);
	my $inverse=$matrix->inverse;
	print $inverse->element(1,1),"\n";
}

これを実行すると以下のようになる.

1.291666666667

足し算,掛け算,引き算,累乗もできる.割り算はできない.以下のようにする.$new1 は足し算,$new2 は掛け算,$new3 は引き算,$new4 は要素の定数倍,$new5 は累乗の結果を示す.累乗は整数であることが求められる.この方法では行列の平方根は求まらない.

#!/usr/bin/env perl
use strict;
use warnings;
use Math::MatrixReal;

MAIN:
{
	my @matrix;
	my $k=1;
	for(my $i=0;$i<3;$i++)
	{
		for(my $j=0;$j<3;$j++)
		{
			$matrix[$i][$j]=$k**2;
			$k++;
		}
	}
	my $matrix=Math::MatrixReal->new_from_rows(\@matrix);
	my $inverse=$matrix->inverse;
	
	my $new1=$matrix+$inverse;
	my $new2=$matrix*$inverse;
	my $new3=$matrix-$inverse;
	my $new4=$matrix*5;
	my $new5=$matrix**5;
	
	print $new2;
}

これを実行すると以下のようになる.$new2 は行列 $matrix とその逆行列 $inverse の積なので,結果は確かに単位行列になっていることが確認できる.

[  1.000000000000E+00  8.881784197001E-16  2.220446049250E-16 ]
[  0.000000000000E+00  1.000000000000E+00  0.000000000000E+00 ]
[  0.000000000000E+00  0.000000000000E+00  1.000000000000E+00 ]
Hatena Google+