2010-08-02
Perl豆知識
知っておくと何かとPerlがイメージしやすくなるかもしれないことをいろいろと追加していきます。
ファイル読込のショートカット
使い捨てのスクリプトを作成する場合は、ファイルオープンの記述を行うのは少し面倒です。ダイヤモンド演算子を単独で使えば、コマンドライン引数、あるいは標準入力から1行づつファイルの読込ができます。
# コマンドライン perl script.pl file1 file2
# ファイルから1行づつ読み込み while(my $line = <>) { }
この記述は
while (defined(my $line = <>)) { }
と同じ意味を持つので0だけが含まれる行なども、正しく読み込んでくれるので安心です。
変数展開の注意
変数名の後にコロンやアンダーバーが続いていると正しく変数展開を行うことができません。そのような場合は「{}」でくくって明示的に変数名を示します。
my $name = 'aaa'; my $message = "${name}::aaa ${name}_ppp";
シンボルテーブルを覗いてみる
変数やサブルーチンなどの名前が登録されているデータ構造です。各パッケージのシンボルは「::」をパッケージ名の末尾に付けた変数に格納されています。
# シンボルテーブル %main:: %CGI:: %File::Basename::
each関数はwhileの中だけで使う
each関数は内部的にイテレータを持っているので、一度だけ使うとイテレータが進んだままになってしまいます。
# イテレータが進んだままになってしまう。 my ($key, $value) = each %hash;
keys関数を作用させるとイテレータはリセットされますが、あまり良い方法ではないでしょう。
# イテレータのリセット keys %hash;
each関数はwhileループの中でだけ利用しましょう。
while(my ($key, $value) = each %hash) { }
print関数に渡すファイルハンドルは第一引数ではない
変な仕様です。print関数に渡すファイルハンドルは第一引数ではないです。ファイルハンドルの後ろにはカンマがありません。
# $fhは第一引数ではない。 print $fh $output;
これは間接オブジェクト記法と呼ばれ次と同じ意味を持ちます。
$fh->print($output);
WindowsではIO::Pollやselectはソケットに対してしかうまくいかない
Windowsでは非同期IO処理はソケットに対してしか行うことができません。ファイルに対してはできません。
Windowsではglob関数の引数に空白が含まれているとうまく動かない
Windowsではglob関数の引数に空白が含まれているとうまく動きません。なんとかこれをうまくいかせるには、ダブルクォートで囲む必要があります。
my @files = glob('"C:/Documents and Settings/*.*"');
サブルーチンの括弧が必要な場合
サブルーチンがすでに宣言されていれば括弧はいりません。
# すでにさ産ルーチンが宣言されている場合は括弧がいらない。 sub func1 { print $_[0] } func1 'aaaa';
インポートした場合も同じです。
# インポートした場合も括弧はいらない use Carp 'croak'; croak 'aaa';
後ろで宣言されている場合は括弧が必要です。
# 後ろで宣言されている場合は括弧が必要 func1('aaa'); sub func1 { print 1 }
完全修飾名で呼び出す場合も括弧はいります。
# 完全修飾名で呼び出す場合は括弧が必要 use Carp; Carp::croak('aaa');
デリファレンスの{}は省略できる。
デリファレンスの {} は対象が単純な変数であれば省略できます。
# {} の省略なし @{$array_ref} # {} の省略 @$array_ref
無名サブルーチンは最初から最後まで存在する
動的に作成したように見える無名サブルーチンはプログラムの最初にコンパイルされて、プログラムの最後に破棄されます。次のコードで生成されるのはサブルーチンのリファレンスであって、サブルーチンそのものではないです。ごちゃまぜになりやすいので注意。
{ # 生成されるのはサブルーチンのリファレンスでサブルーチンそのものではない my $sub = sub { # ... } }
正規表現でのリストコンテキスト
正規表現を使ってマッチした文字の一部分を取得したい場合はif文と組み合わせて次のように書きます。
if ($str =~ /正規表現/) { my $match1 = $1; my $match2 = $2; }
もうひとつ書き方があって、正規表現をリストコンテキストで評価してマッチした文字を取得することもできます。
my ($match1, $match2) = $str =~ /正規表現/;
正規表現の囲み文字の変更
通常は正規表現は次のように書きます。
$str =~ /正規表現/
もうひとつ同じ意味を持つ書き方があります。mを使って上記と同じ意味になります。
$str =~ m/正規表現/;
これは何のためにあるかというと正規表現の中で「/」がたくさん出てくる場合にエスケープするのはとても見にくくなると思った場合に正規表現の囲み文字を変えることができます。囲み文字を「#」に変更した例です。
$str =~ m#http://aaa.com#;
ord関数はordinalの略
文字列を渡すとコードポイントを返却してくれるord関数はordinalの略。これは日本語に訳すと序数という意味。ちなみに対になっているchr関数はコードポイントを渡すと文字に変換してくれます。
ord関数 <-> chr関数
orは「左辺が真でなければ」と英文的に読みます。
orはもともと論理演算子なのですが、論理演算子としては使われずに条件分岐に使われることがほとんどです。
A or B
Perlのor演算子は左辺(A)が真であった場合は、右辺(B)の結果がどうであろうと「A or B」は真になるので、右辺を実行しないという特徴があります。条件分岐に利用される場合はこの特徴が利用されています。
つまり左辺(A)が真の場合には右辺(B)は実行されす、左辺(A)が偽の場合は右辺(B)が実行されます。英文的に読むと「左辺(A)が真でなければ右辺(B)を実効する」と読めます。