ホーム > 読んだ >

初めてのPerl 第2版

書誌

tagPerl
authorRandal L. Scbwartz, Tom Christiansen
editor近藤嘉雪(訳)
publisherオライリー・ジャパン
year1998
price3,000
isbn900900-81-8

履歴

editor唯野
2000.1.0x読了
2000.2.27公開
2002.11.28修正
2012.1.17タグ追加

通称リャマ本。Perl のあまりにも有名な入門書である。Perl のオブジェクト指向的な側面など全ての機能を網羅しているわけではないが、とりあえず本書を読めば Perl プログラムを書くことができるようになる。というより本書を読んだら、後は分かっていなくても、求める機能に合わせて必要な箇所を読むというのが Perl 的な学習法というべきだろう。実際に本書はそういう使い方ができるようになっているし、他の参考文献に示したような本と比べてみても、やはりこの本が最もよくまとまっているように思う。

追記

コードの明示などで少し修正しました。(2002.4.24)

メモ

1 Perl 入門

Perl :
Practical Extraction and Report Language (実用的なデータ取得レポート作成言語)
Pathologically Eclectic Rubbish Lister (病的折衷主義のがらくた出力装置)

#!/usr/bin/perl
# Perl での Hello World
print "Hello, World!\n";

Perl のマニュアルページは man perl または perldoc perldoc で参照できる。或いはコミュニティの力を借りるのもよい。(Perl ユーザグループは自分たちのことを Perl Mongers と呼んでいる。)ネットニュースなら com.lang.perl.* が充実している。

  • perl ドキュメントの概観
  • perldelta 以前のバージョンからの変更点
  • perlfaq よくある質問とその答え(FAQ 概要)
    • perlfaq1 Perl に関する非常に一般的な高レベルな情報
    • perlfaq2 Perl のソースやドキュメント、サポートなどの入手法
    • perlfaq3 プログラマ用ツールとプログラミングのサポート
    • perlfaq4 数値、日時、文字列、配列、ハッシュなどデータの扱い
    • perlfaq5 I/O、ファイルハンドル、バッファリング、フォーマット、フッタ
    • perlfaq6 パターンマッチと正規表現
    • perlfaq7 他のセクションにない言語全般の話題
    • perlfaq8 IPC(プロセス間通信)、UI の制御
    • perlfaq9 ネットワーク、インターネット、Web
  • perldata データ構造
  • perlsyn Perl の文法
  • perlop 演算子と手続き
  • perlre 正規表現
  • perlrun 起動とオプション (コマンドラインスイッチ)
  • perlfunc 組み込み関数
  • perlvar 定義済(組み込み)変数
  • perlsub サブルーチン
  • perlmod モジュールの仕組み
  • perlmodlib ライブラリモジュールについて
  • perlform フォーマット
  • perllocale ロケール
  • perlref リファレンス
  • perldsc データ構造入門
  • perllol リストのリスト
  • perltoot OOP のチュートリアル
  • perlobj オブジェクト
  • perltie 単純変数に結びつくオブジェクト
  • perlbot オブジェクトの技と実例
  • perlipc プロセス間通信
  • perldebug デバッグ
  • perldiag 診断メッセージ
  • perlsec セキュリティ
  • perltrap 陥りやすい罠
  • perlstyle スタイルガイド
  • perlpod POD について
  • perlbook 文献案内
  • perlembed C/C++へのPerl組み込み
  • perlapio 内部的なIO抽象IF
  • perlxs XS API
  • perlguts 拡張用内部関数
  • perlcall Cからの呼び出しコンベンション

Perl はインタプリタであるが、いったん中間言語にコンパイルしたコードをインタプリタしている。また Perl では手続き(procedure)と関数(function)が厳密に区別されない。

Perl と構文的な互換のあるわけではないが、意味的に awk と sed のスーパーセットになっている。そのため、a2p ユーティリティで awk スクリプトを Perl スクリプトに、s2p ユーティリティで sed スクリプトを Perl スクリプトに変換できる。但し、シェルスクリプトからの変換ユーティリティは存在しない。

2 スカラーデータ

Perl での変数名プリフィクス。

$スカラー (ちなみに変数名の最大長は 255 文字)
@配列
%ハッシュ
&サブルーチン
*型グロブ

use strict; による変数宣言の強制と -w オプションによる警告を併用するようにする
複雑な式に出会ったら内側から外側へ読み進めてみるとよい
""、"0"、0、undef が偽 Perl での真偽は常にスカラーとして評価される
("00" は真、これによって数値と文字列を同列に評価できる)
Perl での標準ファイルハンドル : STDIN、STDOUT、STDERR
Perl では整数も浮動小数点数も内部的には倍精度浮動小数点数として扱われる
浮動小数点数もインクリメント/デクリメントできる (4.2 を ++ すれば 5.2)
剰余演算はオペランドを整数値にしてから計算を行っている
文字列はピリオド演算子(.)で連結できる .= も合法
リテラル(literal) : 定数(constant)

C と同様に Perl の式も値を持つが、C の &&、|| が 0 か 1 を返すのに対し、Perl では最後に評価した式の値を返す。そのため、「式1 || 式2」で式 1 が偽のときの処理(例えばエラー処理)を式 2 に続けて書くことができる。

this && that; # もし this なら that せよ
this || that; # unless と同じ

逆クォート文字列(``)は外部コマンドの実行結果に対する出力を返す

シングルクォート文字列 ('')
\ や $ はそのまま扱われ変数展開されずエスケープシーケンスも利用できない
例えば \n は バックスラッシュ + n として扱われる

ダブルクォート文字列("")
C の文字列に近く(\ が意味を持つので)エスケープシーケンスが使える
(例えば \ ' : シングルクォート自身、\\ バックスラッシュ自身)
そして、変数展開ができる (変数展開は $ か @ で始まる式で行われる)

Perl は FORTRAN 風のべき乗演算子を持ち「2 ** 3」は 2 の 3 乗を示す
(結果が倍精度浮動小数点数を超えると fatal error になる)

エスケープシーケンス

表記意味
\n改行(newline)
\r復帰(return)
\tタブ(tab)
\f改ぺージ(formfeed)
\bバックスペース(backspace)
\aベル(bell)
\eエスケープ(escape)
\0078 進数
\xff16 進数
\cCコントロール文字
\\逆スラッシュ
\"ダブルクォート
\l次の一文字を小文字にする
\L\Eに出合うまで小文字にする
\u次の一文字を大文字にする
\U\Eに出合うまで大文字にする
\Q\Eまでの全ての非英数字の前に逆スラッシュを挿入
\E\L、\U、\Qを終了

論理積(AND) オペランドのビットが共に 1 なら 1
論理和(OR) オペランドのビットのいずれかが 1 なら 1
排他的論理和(XOR) オペランドのビットが異なれば 1

比較演算子数値文字列
等しい==eq
等しくない!=ne
より小さい<lt
より大きい>gt
より小さいか等しい<=le
より大きいか等しい>=ge
比較結果<=>cmp (左オペランドが右オペランドよりも小さいと -1、等しいと 0、大きいと 1 を返す)

論理演算子は C と同じ &&、||、! のほかに同じ意味を持つ and、or、not を使うことができる。後者は優先順位が低いので、C のように副作用を恐れて式をカッコで囲む必要がない。そのため、どちらかといえば and、or を使うようにすべきである。

if(not defined($a) or not defined($b))
{
    die "・・・";
}

数値演算子で文字列値を扱うと文字列値は自動で数値(10進)に変換される。このとき文字列中の数字以外の文字は全て無視される。(文字しかなかった場合にはエラーなしの 0 として扱われる。)

文字列繰り返し演算子
e.g. "fred" x 3 # "fredfredfred" となる 3 は (2+1) など式の結果でもよい

文字列繰り返し演算子のオペランドはあくまでも文字列でオペランドの順序を入れ替えることはできない。また、繰り返し回数が 1 未満の場合は長さ 0 の文字列として解釈される。

リスト構成演算子
例: (スカラー値 .. スカラー値)
左のスカラー値から右のスカラー値まで 1 ずつ値を増加させる
少数も 1 ずつ増加できるが値の小さくなるリストは作成できない
数値だけでなくアルファベットも補完できる

演算子の優先順位は C にもあるものに関しては C と同じになっている

結合規則演算子
「リスト」演算子(左方向)
-> (メソッド呼び出し、デリファレンス)
しない++、-- (インクリメント、デクリメント)
** (べき乗)
!、~、\、+、- (ビットごと否定(1 の 補数)、ビットごとnot、リファレンス演算子、単項プラス・マイナス)
=~、!~ (マッチする・しない)
*、/、%、x (乗算、除算、剰余、文字列繰り返し)
+、-、. (加算、減算、文字列連結)
<<、>> (ビットシフト演算子)
しない名前付き単項演算子 (chomp など)
しない<、<=、>、>=、lt、le、gt、ge (「非等値性」比較演算子)
しない==、!=、<=>、eq、ne、cmp (「等値性」比較演算子)
& (ビットごとand)
|、^ (ビットごとor、ビットごとxor)
&& (論理and)
|| (論理or)
しない..、... (範囲演算子)
? : (条件演算子) これは if-else と違って式や関数に埋め込める
=、+=、-=、*= など (代入及び代入演算子)
,、=> (カンマ、カンマとして働く矢印)
しないリスト演算子 (右方向)
not (論理not)
and (論理and)
or、xor (論理or、論理xor)

変数名の区切りとして { } を利用できる。

e.g. print "こんにちは${name}san\n";

chop( ) は引数の文字列(スカラー変数)から最後の 1 文字を取り除く。そして切り捨てた文字を返す。改行を専用に取り除くには chomp( ) を使う。chomp( ) は配列が引数だと配列の全要素から改行をまとめて取り除く。

スカラー変数の場所で <STDIN> を使うと、評価されるたびに標準入力から 1 行を読み込んで <STDIN> の値となる。(<STDIN> には通常、最後に改行文字が付くので chomp とセットにするのがよい。)

e.g. chomp($a = <STDIN>);

値が何も設定されていないと、それは未定義値(undef)になる。(数なら 0、文字列なら空文字列。<STDIN> で入力を終えたときなど。)データが undef かどうかのチェックには defined( ) を使う。

e.g. while(defined($name = <NAMELIST>)) # 空文字列と undef は別物

3 配列とリストデータ

Perl にはコンテキスト(文脈)という概念があり、例えば式の lvalue がスカラー変数の場合、式は結果としてスカラー値の返されることを期待しているので、これをスカラーコンテキスト、同様に lvalue がリスト変数だと式は結果としてリスト値の返されることを期待しているリストコンテキストになる。

例えば、配列の要素を参照する場合、配列に入っている値はスカラーなので、それは配列名に $ を付けスカラーコンテキストにする。そして、lvalue がスカラー値ならば、右辺が配列変数であってもスカラーコンテキストになり、その場合は配列の要素数(というスカラー値)が代入される。

@array = (1, 2, 3); # 配列の初期化
$val = $array[0]; # @array の最初の要素を代入
$num = $array; # $num に @array の要素数を代入 (代入先がスカラー)
($list) = @array; # $list には @array の最初の要素を代入 (代入先が要素 1 のリスト)

更に配列をリストデータとして参照すると配列中の要素すべてをつなげて返す。また、配列変数を . か + 演算子で参照すると、要素の数を返す。

@array = ("私は", "太郎", "です");
print @array, "\n"; # リストで表示 -> 私は太郎です
print @array. "\n"; # スカラー変数(文字列)で表示 -> 3

リストリテラル : リストの値を記述するための表記法 カッコで要素を囲む
e.g. ("fred", 4.5, 3) # ( ) だけなら空のリスト

クォートワードによるリストの簡易表現
@a = ("fred", "barney", "betty", "wilma");
@a = qw(fred barney betty wilma); # 上と同じだが初期化で使うと便利

リストが別のリストをネストして持つことはできない。あくまでも一次元リストの並びとして展開される。しかし、変数のみからなるリストは代入式の左辺として利用できる。

($a, $b, $c) = (1, 2, 3);
($a, $b) = ($b, $a); # 値の入替

代入時に要素の数が合わなければ、それは適切に切り捨てや undef 代入となる。また、配列は動的に大きさを変えることができ、添字の範囲外へアクセスしてもエラーになることはない。

添字に負の値を使うと最後の要素から遡ってアクセスする。例えば [-1] は最後の要素を示す。同じように $#array は配列の最後の添字を意味するので、これを使って配列の大きさを制御できる。ちなみに、添字が 0 から始まることに違和感を感じるのであれば、それは要素の前に存在する要素の数(オフセット)を指すように捉えてみるとよい。

スライスを使うとある配列に含まれる複数の要素へまとめてアクセスすることができる。そのとき、スライスの添字に式を使う場合はリストでなければならない。

($fred[0], $fred[1]) = ($fred[1], $fred[0]); # 値の入れ替え
@fred[0, 1] = @fred[1, 0]; # 上と同じ 配列を扱うのでスライスの先頭は @ となる

配列は push と pop で右端から、unshift と shift で左端から要素を追加・削除できる。また reserve は引数のリスト要素を逆順に並べて返し、sort は引数のリストを ASCII コード順(文字列扱い)にソートして返す。

ファイルハンドルをリストコンテキストで使うとファイル終端までの全ての行を改行付きで読み込み、各行を要素にしたリストのかたちで代入する。

単なるスカラー変数の後の [ を配列変数と解釈させないためには \ で補う。

4 制御構造

Perl には C の switch に相当するものがないので、if-elsif-else を使う
(条件の分岐は elsif であり C における else if ではない)
unless は「条件が偽ならば」で if と逆の意味になる
同様の関係が while と until (条件が真になるまで)にも当てはまる
(do{}while/until : do の内容が一度は実行される)
ちなみに next、last、redo は do{}while/until をループとは解釈しない
for 文は C/Java のそれと同じ

$_ は作業用変数としてその時点で指されるスカラー変数を格納する

Perl では if 節に必ずブレース({})が必要だが次の構文の場合は不要になる。この場合、文は右から左へ向かって評価され、文は単純な式でなければならない。つまり、これをネストすることはできない。

文 if(式) # 式が真のとき文を実行 (unless なら偽のとき実行)
文 while(式) # 式が偽になるまで文を実行 (until なら真になるまで実行)

foreach はリストの値をひとつずつスカラー変数に代入してブロックを実行する。このとき処理されるリストが変数の場合には、ループによってリストの内容も書き換わる。(ループ変数がリストのエイリアスになっている。)

foreach $val (@list)  # $val を略せば $_ に値が入る
{
    ・・・
}

last は C の break に近く、その最も内側のループのブロックを抜け出す
next は C の continue に近く、ループを終了せずに残りをスキップする(ループの最後へ移動)
redo は現在のブロックの先頭にジャンプする(但し制御式を再評価しない)
また exit( ) すると、その時点でスクリプトを終了する

Perl ではブロックにラベルを付けることで、任意のブロックへの last、next、redo を行うことができる。ラベル名は関数名などとバッディングしないよう、通常は大文字を使う。(これはファイルハンドラでも同じこと。)そして、ラベルはブロック文の直前にラベル名とコロンの修飾で指定する。但し、ラベルがあってもラベルからブロック内への移動はできない。

SOMELABEL: while(condition)
{
    statement;
    ・・・
    if(another_condition)
    {
        last SOMELABEL;  # SOMELABEL のブロックを抜ける
    }
}

全文を読まれる場合はログインしてください


Up