日本語を表示させるのに以下のようなプログラムはうまく動かないこともある。
print <<__HEHE__; これは日本語ですよ。 __HEHE__このプログラムが JIS で書かれていると失敗すると、結果は K8l!# と表示 されるだけ。これは日本語の部分を Perl 的に解釈(展開?)しようとするから みたい。で、このヒアドキュメントを次のようにクォートすればよい。
print <<'__HEHE__'; これは日本語ですよ。 __HEHE__ついでに、このヒアドキュメントをクォートすることで、printf のフォーマットの 文字列としても使えるようなので、長い文章のうちの少しだけを変更したい ときには便利かもしれない。
printf <<'__HEHE__', scalar localtime; これは日本語ですよ。 これは二行目。 それでもって今日は %s です。 じゃあ、さようなら。 __HEHE__
\n 改行文字 \r 復帰文字 \t タブ \f 改ページ \b バックスペース \a アラートもしくはベル \e エスケープ文字ESC \u 次の一文字は大文字 \l 次の一文字は小文字 \U これ以降、大文字 \L これ以降、小文字 \Q これ以降、英数文字以外の文字の前に逆スラッシュ \E \U, \L, \Q の終了
どちらも変数のスコープとしてはローカルな宣言なのだけれど、 our の方は変数の値をグローバルに保持しておくらしい。 C 言語で、関数内で static 宣言するのと似ている(のか?)。
sub my_count { my $count; return ++$count; } sub our_count { our $count; return ++$count; } for (my $i = 0; $i < 10; ++$i) { printf("my=%d, our=%d\n", my_count(), our_count()); }
を実行すると、結果は、
my=1, our=1 my=1, our=2 my=1, our=3 my=1, our=4 my=1, our=5 my=1, our=6 my=1, our=7 my=1, our=8 my=1, our=9 my=1, our=10
となり、納得。
package class_a; sub new { my $class = shift; return bless {}, $class; } 1;
package class_b; use class_a; our @ISA = qw(class_a); sub new { my $class = shift; my $self = new class_a; return bless $self; } 1;
もともと C 言語でしかプログラミングしたことなくて、最近 perl を覚えたばかりなので、どうしてもポインタが使いたく なる。で、かわりにリファレンスを多用してしまうのだが、 これは果して効率がいいのやら、悪いのやら...
[値] @array = ( "Jan", "Feb", "March" ); [リ] $arrayref = [ "Jan", "Feb", "March" ];
[値] %hash = ( Jan => 31, Feb => 28, March => 31 ); [リ] $hashref = { Jan => 31, Feb => 28, March => 31 };
文字のあとにつける * やら + のやつのこと。だいたい bourne shell と 同じ。
+------------+-------------+-------------------+ | 最長マッチ | 最短マッチ | | +------------+-------------+-------------------+ | * | *? | 0 回以上 | | + | +? | 1 回以上 | | ? | ?? | 0 または 1 回 | | {n,m} | {n,m}? | n 回以上 m 回以下 | | {n,} | {n,}? | n 回以上 | | {n} | {n}? | n 回 | +------------+-------------+-------------------+
spp:Fe+H2O=FeO2;H:2112:100:Stephen P Potter:/home/spp:/bin/tcshに対して
/.*?:/
は最初のコロンでストップする。
+---------+------------------------------+ | (?#...) | コメント | | (?:...) | 後方参照を抑制したブループ化 | | (?=...) | 0 文字幅先読み | | (?!...) | 0 文字幅先読みの否定 | +---------+------------------------------+
ファイルの途中に、
1; __END__という 2 行があると、__END__ 以降の文は全く実行されないので、 なんでもかける。__END__ の後には空行を入れよう。
man perlpod で POD とは何かがわかる。pod2man とかで man に変換してくれる。
1; __END__ =head1 NAME foo - foo module ... =cutという具合に =head1 で始まって =cut で終る。この手の具合の コマンドの前後は、空行、空行。これはたくさんの行を 一遍にコメントアウトしたいときによい。
for、とか foreach って、
foreach VAR (LIST) { }という具合にかくけれど、BLOCK の中の $_ は LIST の要素の alias として使われているので、$_ の値を変えると、LIST の 要素の値も変わってしまう。変数の宣言をするのはいやだけど、 ここは我慢して $_ を使わないのが賢明。 ただし、朗報は、VAR は BLOCK の中のスコープしかなく、同じ global 変数があっても BLOCK を出たら、もとの値をちゃんと入れ直して くれるらしい。ただ、可読性を考えるとちゃんと変数名を考えよう。
正規表現もスカラー変数に入れられる。
$regular = '^[^\W]'; if ( "header" =~ /${regular}/ ) { print "yes\n"; }これを実行すると yes と表示される。
定数らしきものを使いたいときには、
*hello = \"Hello, world!!";とか指定すると、$hello で "Hello, world!!" という「定数」になる。 というか、代入しようとするとエラーになる。
ハッシュ変数を眺めるのに while (($key, $value) = each(%hash)) {...} とかやるけれども、これが曲者で last で途中で抜けちゃうと、次に 同じことをやるときに、あんまりうまくない。以下は簡単な例。
#!/usr/pkg/bin/perl # %hash = ( key1 => value1, key2 => value2, key3 => value3, key4 => value4, key5 => value5 ); while (my ($key, $value) = each(%hash)) { if ( $key eq "key3" ) { last; } } while (my ($key, $value) = each(%hash)) { print "($key, $value)\n"; }で、結果は
(key4, value4) (key5, value5)
と表示される。どうも内部的に iterator が割当られているらしい。 keys(%hash) で初期化されるらしいのだが、その為に keys を呼出すのも、 なんだかなあ... for や foreach も $_ を iterator として使っていて、 見えない変数があるってのは何かやだなぁ。
使用法
use File::Temp qw/ tempfile tempdir /; $dir = tempdir( CLEANUP => 1 ); ($fh, $filename) = tempfile( DIR => $dir ); ($fh, $filename) = tempfile( $template, DIR => $dir); ($fh, $filename) = tempfile( $template, SUFFIX => '.dat');
とりあえず、どんな名前でもいいから一時的なファイルを使用したいときに、 ファイル名を何にするのかという問題がある。POSIX には、
ANSI_SYNOPSIS #include <stdio.h> char *tmpnam(char * s); char *tempnam(char * dir, char * pfx); char *_tmpnam_r(void * reent, char * s); char *_tempnam_r(void * reent, char * dir, char * pfx);という関数があるので、perl の POSIX モジュールからこれを呼び出せばよい。
#!/usr/bin/perl # use POSIX; for (my $i = 1; $i < 10; ++$i) { printf "%s\n", POSIX::tmpnam(); }結果は、違った名前が 10 個表示される。実際にファイルが存在しなくても、 違うファイル名を返してくるので、テンポラリファイル名だけ先にもらって、 後でファイルを open してもOK.
ファイル名なんぞ知りたくない、file handle さえあればよい、という 場合には、IO::File::new_tmpfile() という関数がある。
#!/usr/bin/perl # use IO::File; my @fh; for (my $i = 0; $i < 9; ++$i) { push @fh, $fh = IO::File::new_tmpfile(); printf $fh "%d\n", $i; } foreach $fh (@fh) { seek $fh, 0, 0; read $fh, $buf, 100; printf STDOUT "%d\n", $buf; }結果は、0 1 2 3 ... 9 と表示して、一応ファイルに書き込まれていることが わかる。しかし、close() すると、ファイル名がわからなくなるので、二度と 開けない(本当か?)。
連想配列をデータベース化することで、プロセスを超えた 処理が可能。以下は、実行するごとに1ずつ増えていく。
#!/usr/bin/perl # use Fcntl; use GDBM_File; my %counter; tie %counter, GDBM_File, "counter.db", O_RDWR | O_CREAT, 0644; printf "%d\n", ++$counter{$0}; untie %counter;