Perl
テンプレート:Infobox プログラミング言語 テンプレート:プログラミング言語 Perl(パール)とは、ラリー・ウォールによって開発されたプログラミング言語である。実用性と多様性を重視しており、C言語やsed、awk、シェルスクリプトなど他のプログラミング言語の優れた機能を取り入れている。ウェブ・アプリケーション、システム管理、テキスト処理などのプログラムを書くのに広く用いられている。
言語処理系としてのperlはフリーソフトウェアである。Artistic LicenseおよびGPLのもとで配布されており、誰でもどちらかのライセンスを選択して利用することができる。UNIXやWindowsなど多くのプラットフォーム上で動作する。
特徴
- 強力な文字列処理。正規表現をサポート
- 日本語をはじめとして世界中の言語を処理可能
- 連想配列(ハッシュ)をサポート
- 多次元データ構造が利用可能
- 自由度の高い文法。簡潔にプログラムを記述できる
- 高い後方互換性を持つ
- 数多くのオペレーティングシステムで利用可能
- プログラムの実行には事前コンパイルは不要
- スクリプト言語の中では高い処理速度を持つ
- Unicodeのサポート
- モジュールによる拡張が可能
- 有志によって開発された豊富なモジュール(CPANを参照)
- オブジェクト指向プログラミングのサポート
- リファレンスカウント方式によるガーベッジコレクション
- 例外処理のサポート
- クロージャのサポート
- リフレクションのサポート
Hello world
print "Hello, world!\n";
文法
コメント
「#」以降は行末までがコメントである。
# ここはコメントです。
変数
変数としてスカラ、配列、ハッシュがある。変数名の前にシジル (sigil) と呼ばれる記号でこれらの変数を区別する。スカラのシジルは「$」、配列は「@」、ハッシュは「%」となっている。
変数は初期化の仕方によって、スコープが異なったものになる。
- 変数宣言をせずに初期化された変数 → 大域変数
local
宣言をしてから初期化された変数 → 動的スコープで、ブロック内でのみ有効な局所変数my
宣言をしてから初期化された変数 → 静的スコープで、ブロック内でのみ有効な局所変数
より高速で安全なmy
宣言が導入されたPerl 5.0以降、local
宣言は非推奨となっている[1]。
下のコードは my
を使って変数を宣言し、同時に初期化する例である。local
宣言もキーワードが異なるのみで同様である。
{
my $num = 2 + 3;
my $message = "Hello, world";
my @nums = (0, 1, 2);
my %score = (english => 100, math => 80);
# これらの変数は開き括弧「{」から閉じ括弧「}」までの間で有効。
}
配列およびハッシュの各要素はスカラであり、以下のようにアクセスする。ひとつの要素にアクセスするときは、変数が配列やハッシュであっても「$」を使う。
$nums[0]; # 0
$score{math} # 80
スカラには数値、文字列などを格納することができる。
$jackBauer = 24;
$pi = 3.14159265358979;
$vulcanSalute = 'Live long and Prosper!';
条件分岐
条件分岐を行うには「if ~ elsif ~ else」を利用する。
if (条件1) {
~ 処理1が真の場合の処理 ~
}
elsif (条件2) {
~ 条件1が偽で、条件2が真の場合の処理 ~
}
else {
~ 条件1も条件2も偽の場合の処理 ~
}
条件分岐後の処理は文がひとつの場合でも必ず中括弧「{~}」で囲まねばならない。
ifは修飾子として後置することもできる。この場合は逆に中括弧で囲むことはできず、ひとつの文しか指定できない。
print 'Hello' if 条件 ;
ifに対してunlessが存在する。ifとは反対に条件が満たされなかった場合に処理が実行される。
unless (条件) {
~ 条件が偽の場合の処理 ~
}
print 'Hello' unless 条件 ;
繰り返し
繰り返しには foreach
、for
、while
、do
- while
を利用する。
foreach
はすべての配列の要素を順番に処理したい場合に利用される。
my @names = ('Tom', 'Mike', 'Bred');
foreach my $name (@names) {
# 処理
}
for
は規則性のある仕方で変数を変化させるときに使う。
$sum = 0 ;
for (my $i = 0; $i < 10 ; ++$i) {
$sum += $i;
}
for ($node = $doc->getFirstChild ; $node ; $node = $node->getNextSibling) {
print $node->getNodeValue, "\n";
}
for<code> と <code>foreach<code> は修飾子として後置することもできる。配列の各要素は順に$_という変数に渡される。
print $_ for @names;
<code>while は処理を始める前に条件を検査し、条件が満たされる間、処理が繰り返される。
while (条件) {
# 処理
}
while
には、次の繰り返しに移る前に行いたい処理を continue
ブロックにまとめて書くことができる。
while (条件) {
# 処理
} continue {
# 次の繰り返しの前に行う処理
}
do - while
は処理を行った後に条件を検査し、条件が満たされる間、処理が繰り返される。
do {
# 処理
} while (条件) ;
繰り返し文の制御
last<code> で繰り返しを抜けることができる。<code>while
文で continue
ブロックがある場合には、continue
ブロックの内容は実行されない。
foreach my $v (@values) {
# 0 ≦ $v でない値を見つけたら、その時点で繰り返しをやめる。
last unless 0 <= $v ;
}
next
で次の繰り返しに移行する。next
では、while
文で continue
ブロックがある場合には、次の繰り返し処理に移る前に continue
ブロックの内容は実行が実行される。for
文の場合、次の繰り返し処理に移る前に for
文の3番目の引数文が実行される。
foreach my $v (@values) {
# 0 ≦ $v でない値を見つけたら、次の繰り返し処理に移る。
next unless 0 <= $v ;
}
redo
で次の繰り返しに移行する。redo
では、while
文で continue
ブロックがある場合には、次の繰り返し処理に移る前に continue
ブロックの内容は実行が実行されない。foreach
でも(制御)変数の値は変更されずに最初から同じ処理を繰り返す。for
文の場合、次の繰り返し処理に移る前に for
文の3番目の引数文が実行されない。実のところ redo
は繰り返し文専用の制御構造ではなく、ブロック({
~ }
で囲われたところ)の内側であればどこででも使え、ブロックの先頭に goto
で飛び越すのと全く等価である。
任意の飛び越し
任意の場所に飛び越しを行うには goto
を利用する。goto
の後ろには飛び越し先ブロックのラベルを書く。goto
文は繰り返し文の中やブロックの内側でなくとも、プログラム中のどこにでも記述できる。しかし、繰り返し文の中での飛び越しにはlast
、next
、ブロックの内側であれば redo
を使う方がコードが読みやすくなるので、goto
が使われることは少ない。
goto destination ;
print "この print 文は実行されない。\n" ;
destination: {
print "飛び越し先ブロック\n" ;
}
サブルーチン
サブルーチンは以下のように定義する。
sub hello {
print "Hello, world!\n";
}
呼び出しは以下のとおり。
hello();
hello;
&hello();
サブルーチンは関数としても機能する。その場合、最後に評価した値ないしreturn
で指定された値が戻り値となる。
sub hello {
return "Hello, world\n"; # return は省略可能
}
print hello(); # "Hello, world!" と表示
引数は特殊変数@_
に格納される。
# 丁寧に書いた例
sub mul {
my ($left, $right) = @_;
return $left * $right;
}
sub mul { $_[0] * $_[1] }; # こうも書ける
リファレンス
データに直接アクセスするのではなく、データの存在するメモリアドレスをスカラ値として定義するリファレンスを使用することができる。スカラ、配列、ハッシュ、ファイルハンドル、サブルーチンのリファレンスが存在する。
my $scalar_ref = \$scalar; # スカラへのリファレンス
my $array_ref = \@array; # 配列へのリファレンス
my $hash_ref = \%hash; # ハッシュへのリファレンス
my $sub_ref = \⊂ # サブルーチンへのリファレンス
open my $fh, '<', $file; # $fhがファイルハンドルへのリファレンス
参照元にアクセス、すなわちデリファレンスするには、シジルを変数名の頭につければよい。
my $scalar = $$scalar_ref;
my @array = @$array_ref;
my %hash = %$hash_ref;
my $sub = &$sub_ref(2, 3); # サブルーチン呼び出し -- $sub には戻り値が入る
ただし、配列・ハッシュおよびサブルーチンへのリファレンスに関しては、その要素にアクセスするのに(あるいはサブルーチンを呼び出すのに)->を使うことができる。
$array_ref->[0];
$hash_ref->{two};
$sub_ref->(2, 3);
配列・ハッシュについては、配列名・ハッシュ名が定義されておらず、リファレンスからのみアクセスできる無名配列・無名ハッシュを作成することができる。
my $array_ref = [0, 1, 2]; # 無名配列
my $hash_ref = {zero => 0, one => 1, two => 2}; # 無名ハッシュ
また、無名サブルーチンを作ることもできる。
my $sub_ref = sub { $_[0] * $_[1] };
print $sub_ref->(2, 3), "\n"; # 6 を出力
print &$sub_ref(2, 3), "\n"; # こうも書けるが、読みにくいためあまり使われない
参照元のデータタイプを調べるには、ref
を使う。
ref 1; # ''
ref $scalar_ref; # 'SCALAR'
ref $array_ref; # 'ARRAY'
ref $hash_ref; # 'HASH'
参照元がオブジェクトの場合、refはそのオブジェクトが所属するパッケージ名(クラス名)を返す。
ref Foo::Bar->new(); # たいてい 'Foo::Bar'
モジュールの利用
モジュールを利用するにはuseを使用する。
use Net::FTP;
モジュールの読み込みと共に関数をインポートしたい場合は、モジュール名に続いて、関数名を並べるのが一般的である。
use File::Basename 'fileparse';
評価コンテキスト
評価コンテキスト、すなわち、構文上何が(リスト、数値、文字列、リファレンス、あるいは何もないのかが)要求されているかの違いにより評価値が変化する。 リストがスカラコンテキストで評価されるとリストの最後の要素に評価され、配列がスカラコンテキストで評価されると配列の長さに評価される。
$x = ("a", "b"); #リストをスカラコンテキストで評価
print $x; # b を出力
@a = ("a", "b");
$x = @a; #配列をスカラコンテキストで評価
print $x; # 2 を出力
($x, $y) = @a; #リストコンテキスト
print $x; # a を出力
意味が大きく変わる表現も存在する。
@match = ("123 a 56 x" =~ m/\d+/g); #リストコンテキスト (全てを一度にマッチ)
# @match => ("123", "56")
$match = ("123 a 56 x" =~ m/\d+/g); #スカラコンテキスト (順次マッチ)
# $match => "1"
ブロックを呼び出したコンテキストを wantarray
で判別することができる。したがって、コンテキストによって返り値を切り替えるような関数をユーザーが定義することもできる。
例外処理
例外を発生させるにはdie関数を使う。例外が発生するとプログラムはメッセージを出力して終了する。
die "例外が発生しました。";
例外をキャッチするには「eval { };」を使用する。例外が発生した場合は特殊変数「$@」にメッセージが代入される。「$@」の値を調べることで例外が発生した場合の処理を記述できる。
eval {
例外が発生する処理
};
if ($@) {
例外が発生した場合の処理
}
パッケージ
Perlにおけるパッケージとは、一般的に名前空間と呼ばれる機能のことである。パッケージを宣言するには「package」を使う。
package Foo;
パッケージ内で宣言されたパッケージ変数とサブルーチンはパッケージに属するものとなる。パッケージ変数を宣言するには「our」を使う。パッケージ変数には大文字を利用するのが一般的である。
package Foo;
our $NUM = 1;
sub sum {
...
}
package Bar;
our $NUM = 2;
sub sum {
...
}
上記において、Fooパッケージのパッケージ変数$NUMとBarパッケージのパッケージ変数$NUMはまったく別の変数である。またFooパッケージのsumとBarパッケージのsumはまったく別のサブルーチンである。パッケージ変数やサブルーチンはパッケージごとに定義することができる。
自パッケージ内であれば、パッケージ名の指定を行わずに、パッケージ変数やサブルーチンを参照することができる。
package Foo;
our $NUM = 1;
sub sum {
...
}
print $NUM;
print sum();
他のパッケージから参照するには、完全修飾を行う必要がある。mainはデフォルトのパッケージをあらわす。
package Foo;
our $NUM = 1;
sub sum {
...
}
package main;
print $Foo::NUM;
print Foo::sum();
オブジェクト
Perlでは、上記のリファレンスとパッケージを組み合わせることにより、クラスベースのオブジェクト指向を実現している。
package Class;
# コンストラクタ
sub new {
my $class = shift;
my $self = {@_};
bless $self, $class;
}
# アクセサ
sub meth {
my $self = shift;
$self->{meth} = shift if @_;
$self->{meth};
}
オブジェクトを使うときは以下のようにする。
my $obj = Class->new(meth => 'od');
warn $obj->meth; # 'od';
なぜこれが動くのかというと実は、Perlはこれを以下のように解釈している。
my $obj = Class::new('Class', meth => 'od');
warn Class::meth($obj);
Perlにおいて、クラスはただのパッケージであり、オブジェクトはただのblessされたリファレンスであり、そしてメソッドは第一引数にオブジェクトをとるただのサブルーチンである。これはPerl 4との互換性を考慮してこのような「後付け」の設計となったのだが、驚くべき柔軟性を示す。これだけで継承も委譲も出来てしまうのだ。最初からオブジェクト指向のもとに設計された言語から見ると見た目は変であるが、それらの言語にまさるとも劣らないオブジェクト機能をPerlは持っている。
ドキュメンテーション
ドキュメンテーションはPODを用いて記述する。
=head1 NAME
foo.pl
=head1 DESCRIPTION
this script is ...
=cut
ワンライナー
コマンドラインからワンライナーと呼ばれる機能を使って、Perlを実行することができる。
perl -e 'print "Hello, world!\n"'
perl -le 'print "Hello, world!"'
推奨されている記述
以下の2行をプログラムの先頭に記述することが強く推奨されている。
use strict;
use warnings;
strict は潜在的な問題をコンパイル時に調べるためのものであり、warnings は警告の出力を有効にするためものである。perl インタプリタを起動するときのコマンドラインオプションの -w とは似ているが同じではない。warnings の方がより細かいので use warnings を使って -w オプションは省略すればよい。
また、use で 5.11.0 以降のバージョン番号を指定した場合にはデフォルトで use strict が有効になるため[2]、書くことが推奨されるのは use warnings のみとなる。
use 5.12.0;
use warnings;
Perl 5.10 で追加された機能
Perl 5.10.0以降では改行を自動的に出力するsayが使えるようになった。
use 5.10.0; # 5.10未満のPerlでの動作を制限するとともに、5.10での追加機能を有効に
say "Hello, world!";
シェルからは-e
オプションの代わりに-E
を使用すれば、追加機能を利用できる。
perl -E 'say "Hello, world!"'
複数行の注釈
PODによる記法を用いると複数行コメントを書くことができる。(あまり利用されない)
=begin comment
ここは
コメント
です。
=end comment
その他の特徴
- スレッド
- Perlのスレッドはデータが丸ごとコピーされるという点で概念的にUNIXやLinuxのforkに近い。iThreads(インタープリタスレッド)と呼ばれており、他のシステムにおけるどのスレッドとも実装は異なる。シグナルと同時に利用することで問題があるとも言われている。もともとWindows版にてforkのような実装を行うためのコードだったものから、発展している。[3]多くのLinuxディストリビューションではiThreadsをオンにして配布しているが、安全性重視をうたっているFreeBSDやOpenBSDの標準ディストリビューションやOpenSolarisでは、iThreadsをオフにしている。
- PerlIOレイヤ
- 入出力操作に手を加えることができる。各レイヤはC言語で実装できるため高速である。
モジュール
Perlプログラムには、モジュールによって機能を付加することができる。たとえば、他のプログラムやネットワークとの通信、各種ファイル形式の取り扱い、数学的な計算など、数多くのモジュールが存在する。PerlにはCPANというモジュールを体系的に管理するインターネット上のシステムがある。インターネットに接続しているならば、CPANにアクセスして、モジュールをインストールすることが可能である。
標準モジュール
Perlには標準で利用できるモジュールが数多く存在する。
- base - クラスの継承
- Benchmark - ベンチマーク
- Carp - 呼び出し元の観点で例外を発生
- Cwd - カレントディレクトリのパスを取得
- Data::Dumper - 変数の内容を出力
- Digest::MD5 - MD5値
- Digest::SHA - SHA-1/224/256/384/512
- Encode - 文字列のエンコード・デコード
- utf8 - utf8プラグマ
- Exporter - 関数のエクスポート
- File::Basename - ファイルのベース名とディレクトリ名の取得
- File::Copy - ファイルの移動とコピー
- File::Path - 複数階層のディレクトリの作成と削除
- File::Spec - ファイル名に対する移植性のある処理
- File::Temp - 一時ファイルの生成
- FindBin - スクリプトが存在するディレクトリのパスの取得
- Getopt::Long - コマンドライン引数の処理
- lib - モジュールの検索パスを追加
- List::Util - 配列に対する処理
- Net::FTP - FTPクライアント
- Scalar::Util - スカラ値のユーティリティ
- Storable - データの直列化
- Sys::Hostname - ホスト名の取得
- Time::Piece - 日付・時刻の扱い
- IO::Socket::INET - ソケット
代表的なCPANモジュール
- テキスト処理
- Text::CSV - CSVファイルの解析
- Text::Diff - diffコマンド
- Template Toolkit - テンプレートシステム
- データベース
- Webアプリケーション
- CGI - CGIプログラミング
- Plack - PSGIのリファレンス実装
- Mojolicious - Webフレームワーク
- Catalyst - Webアプリケーションフレームワーク
- Webアクセス
- LWP::UserAgent - WWWクライアント
- データ記述言語の処理
- XML::Simple - XMLをPerlのデータ構造に変換
- XML::LibXML - XMLのサポート
- JSON - JSONのサポート
- YAML - YAMLのサポート
歴史
バージョン | 公開日 | 内容 |
---|---|---|
1.0 | 1987年12月18日 |
|
2.0 | 1988年6月05日 |
|
3.0 | 1989年10月18日 |
|
4.0 | 1991年3月21日 |
|
5.0 | 1994年10月17日 |
|
5.5.0 | 1998年7月22日 |
|
5.6.0 | 2000年5月22日 |
|
5.8.0 | 2002年7月18日 |
|
5.10.0 | 2007年12月18日 | |
5.12.0 | 2010年4月13日 | |
5.14.0 | 2011年5月14日 |
|
5.16.0 | 2012年5月20日 |
|
5.18.0 | 2013年5月18日 |
|
5.20.0 | 2014年5月27日 |
|
エピソード
Perlは当初、新約聖書のマタイによる福音書13章46節の「高価な真珠」にちなんで真珠を意味する「pearl」と名付けられた。ラリー・ウォールは肯定的な意味を持つ短い名前を選びたいと考えていて、彼によれば3文字および4文字の単語を辞書から探したが良いのが見つからなかったということである。また、彼は妻のグロリアにちなんで名前を付けることも考えたが、家族の会話でまぎらわしいために却下となった。
Perlの正式なリリースの前に、すでに「pearl」という名前のプログラミング言語が存在する[1]ことに気づき、綴りを変更して「Perl」とした。このようにPerlは略語ではなく、もともと意味はないが、あとからいくつかの意味が考えられている。開発者ラリー自身によると、「practical extraction and report language」(実用的なデータ取得レポート作成言語)という意味を持ち、同時に 「pathologically eclectic rubbish lister」(病的折衷主義のガラクタ出力装置)[4]という少し皮肉な意味も込められている。
処理系
Perlという名称の記述においては、若干の注意が必要である。プログラミング言語としてのPerlを示すときは「Perl」というように、頭文字を大文字にして固有名詞であることをはっきりさせる。この「Perl」という表記では処理系のことは含まれない。Perl 5の現在開発されている唯一の処理系は「perl」という、すべて小文字で記述される名前の処理系である。一般に「perlだけがPerlを解釈することができる」という表現がなされる。「PERL」のようにすべてを大文字にするのは誤りである。
このようにPerl 5現在において、Perlとは言語の名前であると同時に唯一の処理系の名前でもある。この処理系はC言語で書かれている。スクリプトは実行前に仮想機械向けにコンパイルされ、コンパイルされたバイトコードが実行される(ランタイムコンパイル)。そのため、厳密にはインタプリタとは異なる。
Pythonのように一旦生成したバイトコードを保存して再利用することは少ないが、これは現在のPerlのランタイムコンパイルが高速で、バイトコードから実行するメリットがあまりないことが理由の一つである。コンパイル済みコードの再利用としてはむしろmod_perlのような形式が好まれている。
PAR (Perl Archive Toolkit) というPerlスクリプトを実行環境ごとアーカイブし、単一のファイルにまとめるためのツールキットも存在する。JARのPerl版と考えてよい。実行可能ファイルを作ることもできるため、アプリケーションの配布に適する。しかしその場合はPerl実行環境をまるごと含むため、ファイルサイズが大きくなる傾向にある。
Perlの姉妹言語としてPerl6が存在する。Perl6はParrotというバーチャルマシンの上で動作する。現在、ParrotCodeへのコンパイルを行うRakudo Starという処理系やHaskellで書かれたPugsという処理系などの複数の実装が公開されている。なおPerl6はPerlと互換性を持たない。
代表的なアプリケーション
Web アプリケーションや管理ツールの多くが Perl で書かれている。
脚注
- ↑ テンプレート:Cite web
- ↑ http://perldoc.jp/docs/perl/5.12.0/perl5120delta.pod#Implicit32strictures
- ↑ http://perldoc.perl.org/perlfork.html perlfork - Perl's fork() emulation
- ↑ プログラミング Perl VOLUME 1 ISBN 4-87311-096-3
参考文献
- ラリー・ウォール、ジョン・オーワント、トム・クリスチャンセン著、近藤嘉雪訳『プログラミング Perl』VOLUME 1 (ISBN 4-87311-096-3), 2 (ISBN 4-87311-097-1), オライリー・ジャパン、2002年
関連項目
外部リンク
- The Perl Programming Language - Perlの公式サイト
- Perl programming documentation - Perlの公式ドキュメント
- perldoc.jp - Perlの公式ドキュメントの日本語訳
- CPAN - Perlのモジュールの配布を行うサイト
- Perl.com - オライリーによるPerlのウェブサイト
- ActivePerl - ActiveState社のPerlディストリビューション。Win32版はWindows環境で最も利用される。
- Chocolate Perl - Perlのディストリビューションのひとつ
- Vanilla Perl - Perlのディストリビューションのひとつ
- Strawberry Perl - Perlのディストリビューションのひとつ
- PSGI/Plack - WSGIのPerlによる実装
- Japan Perl Association - YAPC::Asiaを主催する一般社団法人