日本語 man コマンド類 (ja-man-1.1j_5) と日本語 man ドキュメント (ja-man-doc-5.4 (5.4-RELEASE 用) など) をインストールすると、以下のような man コマンド閲覧、キーワード検索が コンソールからできるようになります。
4.11-RELEASE-K, 5.4-RELEASE-K, 5.5-RELEASE-K, 6.0-RELEASE-K から 6.4-RELEASE-K, 7.0-RELEASE-K から 7.2-RELEASE-K, 8.0-RELEASE-K は、プライベート版 (小金丸が編集してまとめたもの) ですが、 より多くの翻訳したファイルが含まれています。 (5.4-RELEASE-K から 6.4-RELEASE-K, 7.0-RELEASE-K から 7.2-RELEASE-K, 8.0-RELEASE-K は、全翻訳済み)
6.4-STABLE-K, 7.2-STABLE-K, 8.0-STABLE-K は現在、 作成中で日々更新されています。 最新の snapshots を元に作成しています。
PERL(1) PERL(1)
名称
perl - 実用的抽出とレポートのための言語
書式
perl [options] filename args
解説
perl は、任意のテキストファイルを走査し、そこから情報を取
り出し、情報に基づいたレポートを出力するために最適化された
インタプリタ言語です。また、多くのシステム管理作業に適した
言語でもあります。 perl は美しい (小さい、エレガン ト、 最
小) というよりは、むしろ実用的 (使いやすい、効率的、完全)
であることをめざしています。 perl は、C, sed, awk, and sh,
の最も良いところを組み合わせてある (作者の意向としては、で
ありますが) ので、これらの言語になじみのある人には、容易に
使 え る でしょう。 (言語歴史学者なら、csh, Pascal, そして
BASIC-PLUS の痕跡にさえも気がつくでしょう。) 式の書式は、C
のものに極めて似ています。他の多くの UNIX ユーティリティと
異なり、 perl は、データのサイズを勝手に制限するようなこと
は なく (メモリのある限りです)、ファイル全体を一つの文字列
として読み込んでしまえます。再帰の深さには制限があり ま せ
ん。連想配列で使われるハッシュテーブルは、パフォーマンスの
低下を防ぐため、必要に応じて大きくなります。 perl は、大量
のデータを非常に迅速に走査する洗練されたパターンマッチテク
ニックを使います。テキスト走査に最適化されてはいま す が、
perl はバイナリデータも扱うこともできて、(dbm が使えるな
ら) 連想配列に似た dbm ファイルを作れます。 setuid perl ス
クリプトは、多くの馬鹿らしいセキュリティホールを防ぐデータ
フロー追跡機構により、C のプログラムより安全です。普通なら
sed, awk, sh を使うような問題で、その能力を越えていたり、
もう少し速く走らせなければならなかったり、くだらないことを
C で書きたくないような場合に perl がぴったりです。既存の
sed や awk スクリプトを perl スクリプトにする変換プログ ラ
ムもあります。さあ、宣伝はこれで十分でしょう。
まず始めに、 perl 次の場所からスクリプトを探します。
1. コマンドライン上の -e スイッチで指定された行。
2. コ マンドライン上で、最初に指定されたファイルの内容。
(#! の表記をサポートするシステムは、インタプリタをこう
して起動します)
3. 標準入力から暗黙のうちに読み込まれます。これは、ファイ
ル名の指定が一つもない場合にだけ働きます。-- 標準入 力
スクリプトに引数を渡すには、スクリプト名として明示的に
- を指定しなければなりません。
スクリプトを見つけると、 perl は内部形式にコンパイルし、ス
クリプトが文法的に正しければそれを実行します。
オプション
注意: 最初にこのセクションを読んでも意味がわからないかもし
れません。簡単なリファレンスとして前半部分になっています。
一文字オプションは、次に続くオプションとくっつけてもかまい
ません。 #! 構造を使うスクリプトを起動する際には一つの引数
しか許されないので、特に便利です。例:
#!/usr/bin/perl -spi.bak # -s -p -i.bak と同じ
...
以下のオプションがあります:
-0数字
レコードセパレータ ($/) を 8 進数で指定します。数字が
ないと、ヌルキャラクタがセパレータになります。他の コ
マ ンドラインスイッチは、前に置くか、もしくは数字の後
に続けます。例えば、ヌル文字を終端としたファイル名 を
表 示 可 能なバージョンの find なら、このように書けま
す。
find . -name '*.bak' -print0 | perl -n0e unlink
00 は特殊な値で、 perl はファイルをパラグラフモードで
読 み込みます。 0777 という値を使うと、この値の文字は
ないので、ファイル全体を読み込みます。
-a -n や -p オプションと一緒に用いて、オートスプリットモ
ー ドを ON にします。 -n や -p オプションで自動的に生
成される while ループの内側の最初のところで、@F 配 列
に対して暗黙の split コマンドが行なわれます。
perl -ane 'print pop(@F), "\n";'
は、次の例と同等になります。
while (<>) {
@F = split(' ');
print pop(@F), "\n";
}
-c perl スクリプトの文法をチェックし、実行せずに終了しま
す。
-d perl デバッガのもとでスクリプトを実行します。デバッグ
のセクションを参照して下さい。
-D数字
デ バッグフラッグをセットします。スクリプトがどのよう
に実行されるかを見るには、 -D14 を使います。 (これ は
デ バッグ機能を perl に組み込んでコンパイルした時にの
み動作します。) -D1024 も有用な値で、コンパイルされた
文法ツリーをリストします。 -D512 を使うと、コンパイル
された正規表現を出力します。
-e コマンドライン
一行スクリプトを入力する場合に使えます。複数行スク リ
プ トを組み立てるには、複数の -e コマンドを指定すれば
できます。 -e が与えられると、 perl は引数のリスト の
中からスクリプトファイル名を探しません。
-i拡張子
<> 構造で処理されるファイルをその場で修正することを指
定します。入力ファイルをリネームし、出力ファイルを 元
の名前でオープンし、出力ファイルを print 文のデフォル
ト出力にすることで処理されます。拡張子が与え ら れ れ
ば、 バックアップファイルの名前として元のファイル名に
その拡張子を加えたものが使われます。拡張子が与えら れ
な け れ ば、 バッ クアップファイルは作成されません。
"perl -p -i.bak -e "s/foo/bar/;" ... " を実行すること
は、次のスクリプトと同じです。
#!/usr/bin/perl -pi.bak
s/foo/bar/;
これは以下のものとも同等になります。
#!/usr/bin/perl
while (<>) {
if ($ARGV ne $oldargv) {
rename($ARGV, $ARGV . '.bak');
open(ARGVOUT, ">$ARGV");
select(ARGVOUT);
$oldargv = $ARGV;
}
s/foo/bar/;
}
continue {
print; # 元の名前のファイルに出力する
}
select(STDOUT);
た だし、 -i を用いた方法では、ファイル名が変更された
時刻を知るために $ARGV と $oldargv を比較する必要がな
い という点が異なります。実際にはファイルハンドルとし
て ARGVOUT がセレクトされて使われます。 STDOUT が デ
フォ ルト出力のファイルハンドルとして保存され、ループ
のあとで戻されることに注意して下さい。
入力ファイルすべてに追加を行なう場合や、行番 号 を リ
セッ トしたりする場合、各入力ファイルの終わりを知るた
めに `eof' を使うことができます。 (eof の例を参照して
下さい)
-Iディレクトリ
-P と一緒に用いて C プリプロセッサにインクルードファ
イルの位置を知らせます。デフォルトで は、/usr/include
と /usr/lib/perl を検索します。
-l8進数
行 末処理を自動的に行ないます。これには二つの効果があ
ります。まず、 -n や -p と共に使われることで、行タ ー
ミネータを自動的に除きます。二つ目は、$\ が、 8進数を
セットし、print 文がすべて最後に行末文字をつけると い
うことです。 8進数が省略された場合は、$\ に $/ の現在
の値をセットします。例えば、行を 80 桁に切り揃える た
めには:
perl -lpe 'substr($_, 80) = ""'
$\ = $/ という代入はコマンドラインスイッチが処理され
る時に行なわれるので、 -l スイッチに -0 が続 く と き
は、 入力レコードセパレータと出力レコードセパレータが
異なることもあり得るということに注意して下さい。
gnufind / -print0 | perl -ln0e 'print "found $_" if -p'
これは、$\ に改行をセットし、$/ にはヌル文字をセッ ト
します。
-n スクリプトの前後に下に示すループがあるものとして perl
を起動します。こうすると、引数のファイル全部につい て
"sed -n" または awk と同じような繰り返しが行なわれま
す:
while (<>) {
... # ここにスクリプトが来ます
}
デフォルトで入力行の出力はされないことに注意して下 さ
い。 出力したければ -p を参照して下さい。以下は、1 週
間より古いファイルすべてを削除する効率的な方法です。
find . -mtime +7 -print | perl -nle 'unlink;'
この場合、ファイルが見つかるたびにプロセスを開始す る
必要がないので、 find の -exec スイッチを使うより速く
なります。
-p スクリプトの前後に下に示すループがあるものとして perl
を 起動します。こうすると、引数のファイル全部について
sed と同じような繰り返しが行なわれます:
while (<>) {
... # ここにスクリプトが来ます
} continue {
print;
}
入力行は自動的に出力されることに注意して下さい。出 力
を 抑 制 し たければ、 -n スイッチを使って下さい。 -p
は、 -n スイッチに優先します。
-P perl によるコンパイルの前に C プリプロセッサを通し ま
す。 (perl のコメントも cpp の命令も # の文字で始まる
ので、コメントを C プリプロセッサが理解する単語、例え
ば "if" や "else" や "define" で始めてはなりません。)
-s コマンドライン上で、スクリプト名とファイル名の引数 (
または --) の間にある各スイッチについて基本的な解析を
行ないます。スイッチが見つかると、@ARGV から除か れ、
対 応する変数を perl スクリプト内でセットします。以下
のスクリプトでは、-xyz スイッチをつけてスクリプトを起
動したときだけ、"true" を出力します。
#!/usr/bin/perl -s
if ($xyz) { print "true\n"; }
-S スクリプトを探すのに、環境変数 PATH を用います (スク
リプト名が / で始まらないかぎり)。通常は、#! をサポー
ト しないマシンにおいて #! をエミュレートするために用
いられます。次のような使い方です:
#!/usr/bin/perl
eval "exec /usr/bin/perl -S $0 $*"
if $running_under_some_shell;
システムは 1 行目を無視し、スクリプトを /bin/sh に 渡
します。 /bin/sh は perl スクリプトをシェルスクリプト
として実行しようとします。シェルは 2 行目を通常のシェ
ルコマンドとして実行し、perl インタプリタを起動するこ
とになります。システムによっては $0 は必ずしもフル パ
ス 名にならないので、 -S を用いて perl に必要ならばス
クリプトを探すように指示します。 perl がスクリプト を
見 つ け た あ と、 解 析 を 行ないますが、変数 $run
ning_under_some_shell が真になることはないので、2 行
目 を無視します。ファイル名などに含まれるスペースを正
しく扱うには、$* よりも ${1+"$@"} の方がよいでしょ う
が、csh が解釈する場合には動作しません。 csh ではなく
sh で起動するには、あるシステムでは #! 行を、perl で
無 視されるコロンのみに書き換える必要があるかもしれま
せん。その他のシステムではこの方法は使えず、次のよ う
に、csh, sh, perl のどの下でも動作するような、とても
まわりくどい方法をとる必要があります:
eval '(exit $?0)' && eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
& eval 'exec /usr/bin/perl -S $0 $argv:q'
if 0;
-u スクリプトのコンパイルの後、 perl はコアダン プ し ま
す。 このコアダンプから、`undump' プログラム(提供して
いません)を用いて実行可能ファイルに変換できます。こう
す ると、ディスク消費が増えるかわりに (実行ファイルを
strip すれば最小にできます)、スタートアップが速くなり
ます。 (しかし、私のマシンでは "hello world" の実行形
式が約 200K の大きさになります。) 実行形式 を set-id
プ ログラムとして走らせるのなら、通常の perl ではなく
多分 taintperl を用いてコンパイルすべきです。ダンプす
る前に実行したいスクリプトがある場合は、代わりに dump
演算子を使って下さい。注意 : undump が使えるかどう か
はプラットフォームに依存するので、perl の移植によって
は利用できないものもあるかもしれません。
-U 安全でない操作を可能にします。現在の所、"安全でな い"
操 作とは、スーパユーザ権限での実行時にディレクトリを
unlink すること、および汚れチェックで警告が出るような
setuid プログラムを走らせることだけです。
-v perl のバージョンとパッチレベルを出力します。
-w 一度だけ出てくる識別子、セットする前に使用されるスカ
ラ変数に対して、警告を出します。サブルーチンが再定 義
さ れたとき、定義されていないファイルハンドルの参照が
あるとき、リードオンリーでオープンしたファイルハン ド
ル へ書き込もうとしたときにも警告を出します。数値では
なさそうな値に == を使ったときや、サブルーチンが 100
回以上再帰したときにも警告を出します。
-xディレクトリ
ス ク リプトがメッセージに埋め込まれていることを perl
に知らせます。#! で始まり、"perl" という文字列を含 む
最 初の行が現れるまでは、ゴミとして無視されます。その
行に指定した意味のあるスイッチはすべて適用されます (
た だし通常の #! 処理と同じく、スイッチのかたまり一つ
だけです)。ディレクトリ名を指定すると、perl はスク リ
プ トを実行する前にそのディレクトリに移ります。 -x ス
イッチは、先頭のゴミを捨てるだけです。スクリプトの 後
にゴミがある場合は、スクリプトは __END__ で終わらせな
ければなりません (望むなら、スクリプトで後ろのゴミ の
一 部または全部をファイルハンドル DATA 経由で処理する
ことが可能です)。
データの型とオブジェクト
perl には 3 種類のデータ型が有ります: スカラ、スカラ配列、
および連想配列です。通常の配列は添え字が数字ですが、連想配
列の場合は文字列です。
perl における演算や値の解釈は、演算や値のコンテキス ト( 文
脈)からの要求にしばしば依存します。主なコンテキストは三つ:
すなわち文字列、数値、配列です。演算の中には、配列を要求す
るコンテキストでは配列を、そうでなければスカラ値を返すもの
もあります。 (そのような演算子についてはドキュメント内のそ
の演算子のところに記載されています。) スカラ値を返す演算子
は、コンテキストが文字列あるいは数値のどちらを要求している
かは考慮しませんが、スカラ変数およびスカラ値は文字列あるい
は数値のコンテキストの適切な方に解釈されます。スカラはそれ
が ヌル文字列あるいは 0 でなければ論理的に真であると解釈さ
れます。演算子が返す論理値は、真の場合は 1、偽の場合 は 0
または '' (ヌル文字列)です。
実 際には、ヌル文字には二種類あります。define と undefined
です。 undefined のヌル文字列は、エラー、ファイル終端、 初
期化されていない変数や配列要素を参照しようとしたときなど、
実際の値が存在しない場合に返ります。 undefined のヌル文 字
列 は、最初にそれにアクセスしたときに defined となることが
ありますが、その前に defined() 演算子を用いて値が defined
かどうかを知ることができます。
スカラ変数への参照は、それが配列の一部であっても、常に '$'
で始めます。つまりこうです:
$days # 単純なスカラ変数
$days[28] # 配列 @days の 29 番目の要素
$days{'Feb'} # 連想配列の値の一つ
$#days # 配列 @days の最後の添え字
しかし、配列全部や一部の取り出しは '@' で始めます:
@days # ($days[0], $days[1],... $days[n])
@days[3,4,5] # @days[3..5] と同じ
@days{'a','c'} # ($days{'a'},$days{'c'}) と同じ
そして、連想配列全部を扱うには '%' で始めます:
%days # (key1, val1, key2, val2 ...)
これら 8 つはすべて左辺値として扱うことができます。すな わ
ち、代入可能ということです。 (さらに、あるコンテキストでは
代入操作自体も左辺値となり得ます。 -- s, tr, chop のところ
の例を参照して下さい。) スカラへの代入を行なうと、右辺をス
カラのコンテキストで評価するのに対し、配列や配列の一部への
代入は右辺を配列のコンテキストで評価します。
配列 @days の長さを csh のように "$#days" で評価してもかま
いません。 (実際には、通常 0 番目の要素があるので、配列 の
長 さではなく、最後の要素の添え字になります。) $#days に代
入すると、配列の長さが変わります。この方法によって配列を小
さくしても、実際には値は破壊されません。すでに小さくした配
列を大きくすると、もともとあった要素が元に戻ります。大きく
なりそうな配列をあらかじめ大きくしておくと、効率をいくらか
良くすることもできます。 (配列を大きくするには、配列の最後
を 超 え る 要 素 に 代 入を行なう方法もあります。この方法
と、$#whatever へ代入する方法との違いは、間の要素にヌル が
セットされることです) 配列を縮めて空にするには、ヌルリスト
() を代入すればできます。次の二つは全く同等となります。
@whatever = ();
$#whatever = $[ - 1;
配列をスカラのコンテキストで評価すると、配列の長さが返りま
す。次の式は常に真となります:
scalar(@whatever) == $#whatever - $[ + 1;
連想配列をスカラのコンテキストで評価すると、配列が要素を含
む場合かつその場合に限り真の値を返します。 (要素がある場合
に返る値は、使用している bucket の数およびアロケートされて
いる bucket の数から成る文字列で、/ で区切られます。)
多次元配列は直接はサポートされていませんが、連想配列を用い
て 複数の添え字をエミュレートする方法については、$; 変数の
項を参照して下さい。多次元の添え字を 1 次元の添え字に変 換
するサブルーチンを書くこともできます。
各々のデータ型に応じて、それぞれの名前空間があります。衝突
を心配することなく、同じ名前をスカラ変数、配列、連想配列、
ファイルハンドル、サブルーチン名、またはラベルにつけること
ができます。変数や配列への参照は常に '$', '@', '%' で始 ま
る ので、"予約" 語は変数名については実際には使用可能です。
(しかし、ラベルやファイルハンドルについては予約語は使用 で
きません。特殊な文字で始まらないからです。
ヒ ン ト: open(log,'logfile') より open(LOG,'logfile') を
使った方が良いです。大文字のファイルハンドル名を使うと、読
み易さも向上し、将来の予約語になるものとの衝突も避けること
ができるからです。) 大文字小文字の区別は重要です --"FOO",
"Foo", "foo" はすべて異なる名前です。アルファベットで始ま
る名前は数字や下線を含んでもかまいません。アルファベットで
始 まらない名前は 1 文字に限られます。例えば、"$%" や "$$"
です。 (ほとんどの一文字名は perl の予約変数として意味があ
ります。詳細は後ほど述べます。)
数値文字列は通常の浮動小数点や整数の形式で指定します。
12345
12345.67
.23E-10
0xffff # 16 進
0377 # 8 進
4_294_967_296
文 字 列はシングルクォートまたはダブルクォートで区切られま
す。動作はシェルにおけるクォートとよく似ています。ダ ブ ル
クォートで囲まれた文字列にはバックスラッシュや変数の置換が
行なわれます。シングルクォートで囲まれた文字列には行なわれ
ません (\' と \\ を除きます)。通常のバックスラッシュ規則が
改行やタブなどの文字を表すのに使え、更に以下のちょっ と 変
わった形式も使えます:
\t タブ
\n 改行
\r リターン
\f フォームフィード
\b バックスペース
\a アラーム (ベル)
\e エスケープ
\033 8進文字
\x1b 16進文字
\c[ コントロール文字
\l 次の文字を小文字にします
\u 次の文字を大文字にします
\L \E までを小文字にします
\U \E までを大文字にします
\E 大小文字の修飾の終り
改行を直接文字列に書き入れることもできます。すなわち、文字
列は始まった行と異なる行で終わることができることにな り ま
す。これは便利ですが、最後にクォートを忘れると、クォートを
含むかなり離れた別の行を見つけるまで perl はエラーを報告し
ないでしょう。文字列内の変数置換はスカラ変数、通常の配列、
配列の一部に限られます。 (言い換えると、$ や @ で始まる 識
別子と、それに括弧で囲まれた添え字がある場合だけです。) 次
のコードは "The price is $100." を出力します。
$Price = '$100'; # 解釈されません
print "The price is $Price.\n";# 解釈されます
後に続くアルファベットや数字と区別するために、識別子を {}
で囲うことができることを覚えておいて下さい。また、シングル
クォートは識別子として有効な文字であるため、シングルクォー
トで囲まれた文字列は、前の単語とは空白で区切られていなけれ
ばならないことも覚えておきましょう (パッケージの項を参照し
て下さい)。
プ ログラムのその時点での行番号とファイル名を表す __LINE__
と __FILE__ という二つの特殊な文字があります。これらは 独
立したトークンとしてのみ使用でき、文字列中に書き入れること
はできません。さらにトークン __END__ は、実際のファイル が
終 了 する前で、スクリプトの論理的な終了を示すために使えま
す。残りのテキストはすべて無視されますが、ファイルハンドル
DATA から読むことができます。 (ファイルハンドル DATA は、
メインスクリプトからのみデータを読み込めますが、require さ
れ た ファイルや評価された文字列からは読み込めません。) ^D
と ^Z の二つのコントロールキャラクタは __END__ と同義に な
ります。
文法的に解釈不可能な単語は、それがシングルクォートで囲まれ
ているかのように扱われます。このため、アルファベッ ト、 数
字、下線のみからなり、単語はアルファベットで始まらなければ
なりません。ファイルハンドルやラベルと同じく、小文字のみか
ら な る裸の単語は、将来の予約語と衝突する危険があります。
-w スイッチを使えば、perl はそのような単語について警告して
くれます。
配列値をダブルクォートで囲まれた文字列に入れた場合は、配列
の全要素を $" 変数で指定される区切り (デフォルトは空白) で
連結して一つにした文字列になります。 (3.0 以前のバージョン
の perl では、@ はダブルクォートで囲まれた文字列の中のメタ
キャ ラ ク タ で は な かっ た ので、@array, $array[EXPR],
@array[LIST], $array{EXPR}, @array{LIST} の文字列への挿 入
は、配列がプログラムのどこかで参照されている場合、もしくは
予約されている場合にのみ起こります。) 次の二つは同等になり
ます。
$temp = join($",@ARGV);
system "echo $temp";
system "echo @ARGV";
検索パターン (これにもダブルクォートと同じ置換が行なわれま
す) においては、あいまいな場合があります。 /$foo[bar]/ は
/${foo}[bar]/ ([bar]は正規表現の文字クラス) でしょうか、そ
れとも /${foo[bar]}/ ([bar]は配列 @foo の添字) なので しょ
う か。 @foo が存在しないなら、それは明らかに文字クラスで
す。 @foo が存在するなら、perl は [bar]について考え、大 抵
の場合正しい類推をします。それが間違っていたり、あなたが単
に偏執狂なら、上記のように中括弧 {} を入れることで、正しい
解釈をさせることができます。
行指向の引用法はシェルと同様の文法に基づいています。 << の
後に引用文の終わりを示す文字列を指定すると、現在行からその
文字列が現れるまでの行すべてがその値になります。終わりを示
す文字列は識別子 (単語) でも、クォートされたテキストでもか
まいません。クォートされているテキストの場合、通常クォート
で囲む場合と同じくクォートの種類がテキストの扱い方を決めま
す。クォートされていない識別子はダブルクォートされている場
合と同じ動作となります。 (スペースを入れた場合、それは有効
な ヌル識別子として扱われ、最初の空行にマッチします。 --下
の Merry Christmas の例を見て下さい。) 終わりを示す文字 列
はそれだけで (クォートされず、空白を前後につけずに) 書かれ
ていなければなりません。
print <<EOF; # 前の例と同じです
The price is $Price.
EOF
print <<"EOF"; # 上の例と同じです
The price is $Price.
EOF
print << x 10; # ヌル識別子が終わりを示します
Merry Christmas!
print <<`EOC`; # コマンドを実行します
echo hi there
echo lo there
EOC
print <<foo, <<bar; # スタックに積むことができます
I said foo.
foo
I said bar.
bar
配列のリテラルは、個々の値をコンマで区切り、リストを括弧で
囲みます:
(LIST)
配列値を要求しないコンテキストでは、C のコンマ演算子と同じ
く、最後の要素の値が配列の値となります。例えば、
@foo = ('cc', '-E', $bar);
は配列 foo に全配列値を代入しますが、
$foo = ('cc', '-E', $bar);
は変数 bar の値を変数 foo に代入します。変数として実際に存
在する配列のスカラのコンテキストとしての値は、配列の長さに
なることに注意して下さい。次の例では $foo に 3 を代入し ま
す:
@foo = ('cc', '-E', $bar);
$foo = @foo; # $foo は 3 になります
配列リテラルの括弧を閉じる前に余分なコンマがあっても大丈夫
で、以下のように書けます:
@foo = (
1,
2,
3,
);
リストが評価されるとき、リストの要素はすべて配列のコンテキ
ストとして評価され、結果として得られる配列値に、個々の要素
がリストのメンバであったかのようにリストに挿入されます。た
とえば、@foo のすべての要素、@bar のすべての要素、サブルー
チン SomeSub が返すすべての要素を含むリスト--以下
(@foo,@bar,&SomeSub)
の中では、配列の識別ができなくなります。
リストの値は通常の配列と同様に添え字をつけて使えます。例:
$time = (stat($file))[8]; # stat は配列値を返します
$digit = ('a','b','c','d','e','f')[$digit-10];
return (pop(@foo),pop(@foo))[0];
配列のリストは、そのすべての要素が左辺値であるときに限り代
入可能です:
($a, $b, $c) = (1, 2, 3);
($map{'red'}, $map{'blue'}, $map{'green'}) = (0x00f, 0x0f0, 0xf00);
最後の要素は配列や連想配列であってもかまいません:
($a, $b, @rest) = split;
local($a, $b, %rest) = @_;
実際には、リストのどこに配列を入れてもいいのですが、リスト
中の最初の配列がすべての値を埋めてしまうので、その後の要素
は ヌルの値になります。これは local() において便利かもしれ
ません。
連想配列のリテラルは、キーと値として解釈される値の組を含ん
でいます:
# 上記 map への代入と同じ
%map = ('red',0x00f,'blue',0x0f0,'green',0xf00);
スカラのコンテキストへの配列の代入は、代入の右辺の式により
生成される要素の数を返します:
$x = (($foo,$bar) = (3,2,1)); # $x に 2 でなく 3 をセット
知っておかなければならない幾つかの疑似リテラルがあります。
文 字 列 を `` (低アクセント) で囲んだ場合、ちょうどダブル
クォートと同じ変数置換が行なわれます。次にシェルの中のよう
に、コマンドであると解釈され、そのコマンドの出力がこの擬似
リテラルの値となります。スカラのコンテキストでは、全出力か
ら成る一つの文字列が返されます。配列のコンテキストでは、出
力の各行がそれぞれ一つの要素となった配列値が返されます。 (
行 タ ーミネータを変えたい場合には、$/ をセットできます。)
コマンドは擬似リテラルが評価されるたびに実行されます。コマ
ンドの戻り値は、$? に返されます ($? の解釈については予約変
数のセクションを参照して下さい)。 csh の場合と異なり、返さ
れるデータに置換は行なわれません -- 改行は改行として残りま
す。どのシェルとも違って、シングルクォートで囲んでもコマン
ド 内 の 変数名は解釈されてしまいます。 $ をシェルに渡すに
は、バックスラッシュが必要です。
カギ括弧 <> に囲まれたファイルハンドルを評価すると、 そ の
ファ イ ルから次の行を読み込みます (改行が含まれるため EOF
までは決して偽に成りません。 EOF では undefined 値が返りま
す)。 通常はその値を変数に代入する必要がありますが、一つだ
け自動的に代入が起こる状況があります。入力シンボルだ け が
while ループの条件文の中にある場合は(そしてこの場合にかぎ
り)、値は変数 "$_" に自動的に代入されます。 (奇妙に思う か
もしれませんが、ほとんどの perl スクリプトにおいて、この構
文を使うことになるでしょう。) とにかく、次の例はすべて同等
となります。
while ($_ = <STDIN>) { print; }
while (<STDIN>) { print; }
for (;<STDIN>;) { print; }
print while $_ = <STDIN>;
print while <STDIN>;
ファ イ ル ハンドル STDIN, STDOUT, STDERR は予約されていま
す。 (ファイルハンドル stdin, stdout, stderr でも動作し ま
すが、パッケージの中ではグローバルではなくローカルな識別子
として解釈されるので、働きません。) これ以外のファイルハン
ドルは、 open 関数で作成できます。
配列を探すコンテキストの中で <FILEHANDLE> が使われると、す
べての入力行の一行が一要素である配列が返ります。この 方 法
で*巨大*なデータ空間が簡単に作られるので、注意して使って下
さい。
ヌルファイルハンドル <> は特殊で、sed や awk の動 作 を エ
ミュレートするために使えます。 <> からの入力には、標準入力
やコマンドラインに並べられた全ファイルが入ります。動作の仕
方 はこうなります。 <> の最初の評価では、ARGV 配列がチェッ
クされ、それがヌルであると、$ARGV[0] は標準入力をオープ ン
す る '-' にセットされます。次に ARGV 配列がファイル名のリ
ストとして処理されます。次のループは、
while (<>) {
... # 各行に対するコード
}
以下の疑似コードと同等になります。
unshift(@ARGV, '-') if $#ARGV < $[;
while ($ARGV = shift) {
open(ARGV, $ARGV);
while (<ARGV>) {
... # 各行に対するコード
}
}
前者は、書くのが面倒でないというだけで、同じように動作しま
す。実際には、前者でも 配列 ARGV を shift し、現在のファイ
ル名を変数 ARGV に代入します。内部では、ファイルハン ド ル
ARGV を使います --<> は、魔術的な <ARGV> とまったく同義で
す。 (上の疑似コードでは、<ARGV> を魔術的でないものとし て
扱うので、動きません)
ファイル名のリストの配列が残っている限り、最初の <> の前に
@ARGV を変更することができます。行番号 ($.) は入力が一つの
大きなファイルであるかのように増えていきます。 (ファイル毎
に行番号をリセットする方法については eof の例を参照して 下
さい。)
@ARGV に自分でファイルのリストをセットしたい場合は、そうし
て下さい。スクリプトにスイッチを渡したい場合、スクリプトの
前の方に次のようなループを置くことでできます:
while ($_ = $ARGV[0], /^-/) {
shift;
last if /^--$/;
/^-D(.*)/ && ($debug = $1);
/^-v/ && $verbose++;
... # 他のスイッチ
}
while (<>) {
... # 各行に対するコード
}
<> シンボルは一回だけ*偽*を返します。その後、もう一度呼ぶ
と、別の @ARGV リストを処理しているとみなして、 @ARGV が
セッ トされていない場合は STDIN から入力されることになりま
す。
カギ括弧の中の文字列がスカラ変数への参照であるとき (例えば
<$foo>)、 その変数の内容が読み込むべきファイルハンドル名と
なります。
カギ括弧の中の文字列がファイルハンドルではないとき、 検 索
(glob) さ れるファイルパターンと解釈され、コンテキストに
よってファイル名の配列またはリストの中の次のファイルが返さ
れ ます。最初に $ の解釈の一レベルが行なわれますが、<$foo>
は前の段落で説明されたような間接ファイルハンドルとなるため
使 え ま せ ん。 強 制的にファイル名検索と解釈させさければ
<${foo}> のように中括弧 {} を挿入できます。例:
while (<*.c>) {
chmod 0644, $_;
}
は以下と等価です。
open(foo, "echo *.c | tr -s ' \t\r\f' '\\012\\012\\012\\012'|");
while (<foo>) {
chop;
chmod 0644, $_;
}
実際、現在のところこのように実装されています。 (これは、マ
シン上に /bin/csh がなければ、空白を含むファイル名では動か
ないことを意味します。) もちろん、上の操作を行なう一番短い
方法は、
chmod 0644, <*.c>;
です。
文法
perl スクリプトは、一連の宣言とコマンドからなります。 perl
の中で宣言されなければならないものは、レポートフォーマット
とサブルーチンです。これらの宣言の詳しい説明は下のセクショ
ンを参照して下さい。初期化されていないユーザが作成したオブ
ジェクトは、それが代入のように明示的に定義されるまでは、ヌ
ルまたは 0 の値であるとみなされます。コマンド列が各入力 行
に対して実行される sed や awk スクリプトと違って、コマンド
列は一度だけ実行されます。入力ファイル (または複数のファイ
ル) の各行について繰り返しを行うには明示的にループを設けな
ければなりませんが、着目するファイル、行をよりよくコントロ
ー ルすることができます。 (実は、正しくありません -- -n や
-p スイッチで、暗黙のループを行なうことができます。)
宣言は、コマンドを書くことができる場所ならどこにでも書くこ
とができますが、コマンド実行の基本的な流れには影響を与えま
せん -- 宣言は、コンパイル時だけにしか影響を与えません。通
常、すべての宣言はスクリプトの最初か最後のどちらかに置きま
す。
perl は、ほとんどの部分において自由形式言語です。 (唯一 の
例 外 はフォーマット宣言で、理由は実に明白です。) コメント
は、# 文字で指示され、行末までとなります。 /* */ という C
のコメントを使おうとすると、コンテキストにより除算またはパ
ターンマッチと解釈されるので、そういうことはしないで 下 さ
い。
複合文
perl では、複数のコマンド列を中括弧 {} で囲むことで、一つ
のコマンドとして扱うことになり、これをブロックと呼びます。
次のような複合コマンドは、フローコントロールに使われます:
if (EXPR) BLOCK
if (EXPR) BLOCK else BLOCK
if (EXPR) BLOCK elsif (EXPR) BLOCK ... else BLOCK
LABEL while (EXPR) BLOCK
LABEL while (EXPR) BLOCK continue BLOCK
LABEL for (EXPR; EXPR; EXPR) BLOCK
LABEL foreach VAR (ARRAY) BLOCK
LABEL BLOCK continue BLOCK
C や Pascal と違って、これらは文ではなく*ブロック*として定
義されていることに注意して下さい。これは、中括弧 {} が、必
要 である ことを意味します -- 一つの文を置くことは許されま
せん。中括弧 {} なしで書きたい場合は、別の方法があります。
以下はすべて同等のことを行ないます:
if (!open(foo)) { die "Can't open $foo: $!"; }
die "Can't open $foo: $!" unless open(foo);
open(foo) || die "Can't open $foo: $!"; # foo でなければ終わり
open(foo) ? 'hi mom' : die "Can't open $foo: $!";
# 最後のものは、ちょっとエキゾチック
if 文は単純です。 *ブロック*は、常に中括弧 {} で囲まれるた
め、 else が、どの if にかかるかという曖昧さは生じません。
unless を if の代わりに使うと、逆の意味となります。
while 文 は、式が真 (ヌル文字列または 0 でない) である限
り、ブロックを実行し続けます。識別子とコロンからなるラベル
を つ けることもできます。ラベルはループ制御文 next, last,
redo (以下を参照) によって指し示すループの名前となります。
continue ブロックがあると、条件文が再評価される前に必ず実
行され、C における for ループの三番目の部分と同様となり ま
す。こうして、たとえ next 文で継続された場合でもループ変数
はインクリメントできることになります (C の "continue" 文と
同じ)。
while が until に置き換えられると テストの意味は逆になりま
すが、条件判断は最初のループの前に行なわれます。
if や while 文では、"(EXPR)" をブロックに置き換えること が
でき、ブロックの最後のコマンドの値が真なら、条件判断は真と
なります。
for ループは、対応する while と全く同じように動作します:
for ($i = 1; $i < 10; $i++) {
...
}
は、以下と同じになります。
$i = 1;
while ($i < 10) {
...
} continue {
$i++;
}
foreach ループは、通常の配列値について、配列の各要素を変数
VAR に順にセットしながら繰り返します。その変数は、ループに
対して暗黙のうちにローカルであり、それ以前の値はループを抜
け る と 元 の 値に戻ります。 "foreach" キーワードは、実は
"for" キーワードと同じで、 "foreach" を 可 読 性 の た め
に、"for" を簡潔さのために使うことができます。 VAR が省略
されると、$_ が各値にセットされます。 ARRAY が実際の配列 (
配 列を返す式ではなく) の場合、ループ内の VAR を変更するこ
とによって、配列の各要素を変更することができます。例:
for (@ary) { s/foo/bar/; }
foreach $elem (@elements) {
$elem *= 2;
}
for ((10,9,8,7,6,5,4,3,2,1,'BOOM')) {
print $_, "\n"; sleep(1);
}
for (1..15) { print "Merry Christmas\n"; }
foreach $item (split(/:[\\\n:]*/, $ENV{'TERMCAP'})) {
print "Item: $item\n";
}
ブロックそれ自身 (ラベルが付いていても、付いていなくて も)
は、一度だけ実行されるループと等価です。だから、ブロックを
抜けたり再実行するために、すべてのループ制御文を使うことが
で き ま す。 continue ブロックも付けられます。この構成
は、case 構造を作成するには特に有用です。
foo: {
if (/^abc/) { $abc = 1; last foo; }
if (/^def/) { $def = 1; last foo; }
if (/^xyz/) { $xyz = 1; last foo; }
$nothing = 1;
}
同等のものを記述する方法が、既にいくつもあるので、perl に
は公式の switch 文がありません。上記のものに加えて、
foo: {
$abc = 1, last foo if /^abc/;
$def = 1, last foo if /^def/;
$xyz = 1, last foo if /^xyz/;
$nothing = 1;
}
または
foo: {
/^abc/ && do { $abc = 1; last foo; };
/^def/ && do { $def = 1; last foo; };
/^xyz/ && do { $xyz = 1; last foo; };
$nothing = 1;
}
または
foo: {
/^abc/ && ($abc = 1, last foo);
/^def/ && ($def = 1, last foo);
/^xyz/ && ($xyz = 1, last foo);
$nothing = 1;
}
さらに
if (/^abc/)
{ $abc = 1; }
elsif (/^def/)
{ $def = 1; }
elsif (/^xyz/)
{ $xyz = 1; }
else
{$nothing = 1;}
とも書けます。これらはすべて内部で switch 構造に最適化され
るため、perl は直接目的の文にジャンプするので、同じ単純 な
スカラ変数を == や eq や上記のようなパターンマッチで判定す
る限り、50 個の elsif を使っても perl がたくさんの不要な文
を実行するのでは、という心配は不要となります。 (ある特定の
case ステートメントが最適化されているかどうかに興味があ る
なら、 -D1024 スイッチを付けて実行前に文法ツリーを表示する
ことができます。)
単文
単文のみがその副作用を評価される式となります。どの単文もブ
ロックの最後の文でない限り、セミコロンで終らなければなりま
せん。最後の文では、セミコロンはなくてもかまいません。 (そ
れでも、ブロックが一行以上を含んでいるのなら、セミコロンは
あった方が望ましいです)
どの単文も、セミコロンで終る前に一つの修飾子を続けることが
できます。可能な修飾子は以下の通りです:
if EXPR
unless EXPR
while EXPR
until EXPR
if と unless 修飾子は見かけ通りの意味があります。 while と
until 修飾子も見かけ通りの意味 (条件文が始めに評価さ れ ま
す) ですが、 do ブロックや do サブルーチンコマンドが付けら
れたときには異なり、条件式が評価される前に一度だけ実行され
ます。これは、以下のようなループが記述できるようにするため
です:
do {
$_ = <STDIN>;
...
} until $_ eq ".\n";
(後述の do 演算子を参照のこと。修飾子は、どれもループラ ベ
ルを持てないため、後に書かれたループ制御コマンドはこの構造
では動かないことに気をつけて下さい。あしからず。)
式
perl の式は、ほとんど C の式と同じに動作しますが、違いをこ
こに述べます。
以下が perl にあって、C にないものです:
** 指数演算子。
**= 指数代入演算子。
() 配列をヌルに初期化するために使う、ヌルリスト。
. 2 つの文字列の結合演算子。
.= 結合代入演算子。
eq 文 字列の同値性 (== は数値の同値性)。覚えるために
は、"eq" が文字列であると考えれば良いです。 (状 況
に 応 じ て、== が文字列と数値の両方の同値性を表す
awk に慣れている人は、ここでは明示しなければならな
いことに気をつけて下さい !)
ne 文字列の非同値性 (!= は数値の非同値性)。
lt 文字列の less than
gt 文字列の greater than
le 文字列の less than or equal
ge 文字列の greater than or equal
cmp 文字列の比較。 -1, 0, 1 を返します。
<=> 数値の比較。 -1, 0, 1 を返します。
=~ 演算には、検索、変更をデフォルトで文字列 "$_" に対
して行うものがあります。この演算子を用いると、別の
文字列に対してその演算が行われます。右の引数は、検
索パターン、置換、変換です。左の引数は、デフォルト
の "$_" の代わりに検索、置換、変換が行なわれる対象
となるものです。戻り値は、演算の成否を示します。 (
右の引数が検索パターン、置換、変換以外の式なら、実
行時に検索パターンとして解釈されますが、パターンは
式が評価される度にコンパイルされなければならないの
で、明示的な検索より効率的ではありません。) この演
算 子 の優先度は単項マイナス演算子 (-)、autoincre
ment/decrement (++, --) より低く、他のどの演算子よ
りも高くなります。
!~ 戻り値が否定されることを除いて =~ と同じです。
x 繰り返し演算子。左オペランドを右オペランドで指定し
た回数だけ繰り返した文字列を返します。配列のコンテ
キ ス トでは、左オペランドが括弧に入ったリストの場
合、リストを繰り返します。
print '-' x 80; # ダッシュの列を出力します
print '-' x80; # 不正、x80 は識別子
print "\t" x ($tab/8), ' ' x ($tab%8); # タブに変換
@ones = (1) x 80; # 80 個 1 が並んだ配列
@ones = (5) x @ones; # 全要素を 5 にセット
x= 繰り返し代入演算子。スカラに対してのみ動作します。
.. 範囲演算子。コンテキストによって、実際は二つの異な
る演算子になります。配列のコンテキストでは、左の値
から右の値まで一つずつ数を増やした配列を返します。
これは、"for (1..10)" というループや配列の切り出し
(slice) を行なうときに便利です。
ス カラのコンテキストでは、.. は論理値を返します。
この演算子は、flip-flop のように二つの値を 取 り、
sed や awk やいろいろなエディタの行範囲 (comma) 演
算子をエミュレートします。各 .. 演算子はそれ自身の
論理値を保持し、左のオペランドが偽である限り偽とな
ります。左のオペランドが真になると、範囲演算子は、
右のオペランドが真になるまで真となります。その後、
範囲演算子が再び偽となります。 (次に範囲指定演算子
が評価されるまで、偽にはなりません。真になったのと
同じ評価を行った時 (awkと同様) に右のオペランド を
テストして、偽になることがあり得ますが、一度は真を
返します。次の評価まで右のオペランドをテストしたく
な ければ (sed のように)、二つにするかわりに三つの
ドット (...) を使って下さい。) 右のオペランド は、
演算子が "偽" の状態である間は、評価されず、左のオ
ペランドは演算子が "真" である間は評価されません。
|| や && より優先度はやや低くなります。戻り値は、
偽ではヌル文字列に、真では (1で始まる) 連続した 数
に な ります。この数は、範囲指定毎にリセットされま
す。連続した範囲の最後の数は、文字列 'E0' を持って
いて、数値には影響しませんが、終点を除きたい場合に
検索のきっかけになります。数字が 1 より大きくな る
の を 待つことで、始点を除くことができます。スカラ
.. の両方のオペランドが静的である場合、オペラン ド
は暗黙のうちに現在の行番号を表す $. 変数と比べられ
ます。例:
スカラ演算子としては:
if (101 .. 200) { print; } # 100行台を出力します
next line if (1 .. /^$/); # ヘッダ行を読み飛ばします
s/^/> / if (/^$/ .. eof()); # 本体をクォートします
配列としては:
for (101 .. 200) { print; } # $_ を 100回表示します
@foo = @foo[$[ .. $#foo]; # 高価なノーオペレーション
@foo = @foo[$#foo-4 .. $#foo]; # 最後の 5 要素を取り出します
-x ファイルテスト。この単項演算子は一つの引数として、
ファイル名またはファイルハンドルを取り、そのファイ
ルについて、何かが真であるかどうかを見るものです。
引数が省略されると、$_ を調べますが、例外として -t
は STDIN を調べます。真の場合は 1 を、偽の場 合 は
'' を返し、ファイルが存在していない場合は、unde
fined の値を返します。優先度は、論理値や関係演算子
より高くなりますが、算術演算子より低くなります。演
算子は以下の通りです:
-r ファイルを実効 uid/gid で読み込める。
-w ファイルに実効 uid/gid で書き込める。
-x ファイルを実効 uid/gid で実行できる。
-o ファイルの所有者が、実効 uid である。
-R ファイルを実 uid/gid で読み込める。
-W ファイルを実 uid/gid で書き込める。
-X ファイルを実 uid/gid で実行できる。
-O ファイルの所有者が、実 uid である。
-e ファイルが存在する。
-z ファイルサイズが 0 である。
-s ファイルサイズが 0 でない (サイズを返す)。
-f ファイルはプレーンファイルである。
-d ファイルはディレクトリである。
-l ファイルはシンボリックリンクである。
-p ファイルは名前付きパイプ (FIFO) である。
-S ファイルはソケットである。
-b ファイルはブロック特殊ファイルである。
-c ファイルはキャラクタ特殊ファイルである。
-u ファイルには setuid ビットが立っている。
-g ファイルには setgid ビットが立っている。
-k ファイルには sticky ビットが立っている。
-t ファイルハンドルが tty にオープンされている。
-T ファイルはテキストファイルである。
-B ファイルはバイナリファイルである (-T の逆)。
-M スクリプトを開始した時点でのファイルの古さ(単位は日)。
-A アクセス時刻と同じ。
-C inode 変更時刻と同じ。
ファイルパーミッション演算子 -r, -R, -w, -W, -x,
-X の解釈は、単にファイルのモードとユーザの uid,
gid に基づきます。他の理由で、実際にファイル を 読
み、書き、実行ができないことがあるかもしれません。
また、気をつけなけらばならないのは、スーパユーザに
とっ て -r, -R, -w, -W は常に 1 を返し、そのモード
でいずれかの実行ビットが立っていれば、-x, -X も 常
に 1 を返すというところです。従って、スーパユーザ
が実行するスクリプトは、ファイルの実際のモードを決
め る ために stat() を実行したり、一時的に他の uid
を立てる必要があるかもしれません。
例:
while (<>) {
chop;
next unless -f $_; # 特殊ファイルを無視
...
}
-s/a/b/ としても、否定した置換をするわけではないこ
とに注意して下さい。 -exp($foo) とすると、期待通り
に動きますが、-- マイナスの後が一文字の場合、 ファ
イルテストと解釈されます。
-T と -B は以下のように動作します。ファイルの先頭
のブロックあたりに、変なコントロールコードや メ タ
キャラクタのような、おかしな文字がないかどうかを調
べます。おかしな文字が (10%以上) 見つかると、そ れ
は -B ファイル、でなければ -T ファイルとなります。
最初のブロックにヌルが含まれるファイルもバイ ナ リ
ファイルとみなされます。 -T や -B がファイルハンド
ルに使われると、最初のブロックではなく、そのときの
標 準入力バッファが調べられます。ヌルファイル(サイ
ズ 0 のファイル)の場合やファイルハンドルをテストし
ていて、それが EOF である場合、-T と -B は共に真を
返します。
すべてのファイルテスト (と stat 演算子)は、アンダライン 一
つ _ から成る特殊ファイルハンドルを与えられると、システム
コールを保存することによって、その直前に行なわれたファイル
テ スト (または stat演算子) で使われた stat 構造体が使われ
ます。 (この _ の働きは -t では動作せず、lstat と -l が
stat 構造体に実ファイルではなく、シンボリックリンクの値を
残すことを覚えておかなければなりません。) 例:
print "Can do.\n" if -r $a || -w _ || -x _;
stat($filename);
print "Readable\n" if -r _;
print "Writable\n" if -w _;
print "Executable\n" if -x _;
print "Setuid\n" if -u _;
print "Setgid\n" if -g _;
print "Sticky\n" if -k _;
print "Text\n" if -T _;
print "Binary\n" if -B _;
C にあって、 perl にないもの:
単項 & アドレス演算子
単項 * "アドレスを通しての"参照演算子
(TYPE) 型変換演算子。
C のように、 perl は、演算子への引数が皆、静的で、副作用が
ない場合だけコンパイル時にある程度の式の評価を行なってしま
います。特に、変数置換を行なわないリテラル間での文字列の結
合は、コンパイル時に行なわれます。バックスラッシュの解釈も
コンパイル時に起こります。
'Now is the time for all' . "\n" .
'good men to come to.'
これは全部、内部では一つの文字列にされてしまいます。
++ 演算子にはちょっと拡張した細工が施されています。数値 変
数や数値コンテキストとして使われた変数をインクリメントする
と、通常のインクリメントになりますが、変数がヌルでない文字
コ ン テ キ ス ト と し て だ け使われて来ていて、パターン
/^[a-zA-Z]*[0-9]*$/ にマッチする場合は、各文字の範囲をキャ
リー付きで保存し、文字としてインクリメントされます:
print ++($foo = '99'); # prints '100'
print ++($foo = 'a0'); # prints 'a1'
print ++($foo = 'Az'); # prints 'Ba'
print ++($foo = 'zz'); # prints 'aaa'
-- 演算子には、このような細工はありません。
( 配列のコンテキストにおける) 範囲演算子は、最大値と最小値
が文字列の場合に、細工した自動インクリメントアルゴリズムを
使います。すべてのアルファベット文字を得るには、
@alphabet = ('A' .. 'Z');
16 進数を得るには、
$hexdigit = (0 .. 9, 'a' .. 'f')[$num & 15];
始めに 0 を付けた日付を得るには、
@z2 = ('01' .. '31'); print @z2[$mday];
と書けます。 (最後に指定された値が、細工したインクリメント
の生成するシークエンスに含まれていない場合、次の値が最後に
指定された値より長くなるまでシークエンスを続けます。)
|| と && は、0 や 1 を返す C のそれとは違って、最後に評価
された値を返します。だから、ホームディレクトリをみつける移
植性の高い方法は、こうなります。
$home = $ENV{'HOME'} || $ENV{'LOGDIR'} ||
(getpwuid($<))[7] || die "You're homeless!\n";
前述のリテラルや変数に合わせ、以降の節で説明する演算は式中
で項として使えます。これらの演算の幾つかは、引数に*リスト*
を取ります。リストは、スカラや配列値からなります。配列値が
リストの中にあると、その場所に挿入されたように個々の値がリ
ストの中に含まれて、長い一次元配列値を作ることになります。
*リスト* の要素はコンマで区切られていなければなりませ ん。
引数を括弧で囲んでも囲まなくても、演算をリスト出来ます。こ
れは関数呼び出しと同様単項演算子として、演算を使うことがで
きることを意味します。関数呼び出しとして使うには、同じ行の
次のトークンは左括弧でなければなりません。 (空白が間にはさ
まってもかまいません。) そのような関数は、予想される通り最
優先となります。左括弧を持っていないトークンが続くと す れ
ば、それは単項演算子で、リスト演算子かどうかによって、優先
度が決まります。リスト演算子は最も優先度が低くなります。す
べての単項演算子は、関係演算子よりも優先されますが、算術演
算子よりも優先度は低くなります。優先度のセクションを参照し
て下さい。
スカラや配列のコンテキストで使われる演算子の場合、失敗する
と一般に、スカラコンテキストでは undefined 値を返し、配 列
の コンテキストではヌルリストを返します。しかし、*リストを
スカラに変換する一般的な規則はない* ということを忘れないで
下さい。それぞれの演算子は、どの種のスカラを返すのが最も適
当であるかを決めます。ある演算子は、配列のコンテキストとし
て返されるようなリストの長さを返します。リストの最初の値を
返す演算子、リストの最後の値を返す演算子、操作に成功した回
数 を 返す演算子などもあります。一般に、一貫性を求めなけれ
ば、演算子は求めるものを返します。
/PATTERN/
m/PATTERN/ を参照して下さい。
?PATTERN?
これは、 reset 演算子呼び出しの間で一回しかマッ チ
し な い ことを除けば、 /pattern/ 検索と全く同じで
す。これは例えば、一群のファイルの中で、各ファイル
に最初に何かが出現することを見たいとき、便利な最適
化です。そのときのパッケージにローカルな ?? パター
ンだけは、リセットされます。
accept(NEWSOCKET,GENERICSOCKET)
accept システムコールと同じことをします。成功する
と真を、失敗すると偽を返します。プロセス間通信のセ
クションの例を参照して下さい。
alarm(SECONDS)
alarm SECONDS
指定した秒数 (実際には、1 を引いたもの) が経過した
あと、自分のプロセスに SIGALRM を伝えま す。 つ ま
り、alarm(15) な ら、14 秒以上経ったある時点で
SIGALRM を生じます。一度に一つのタイマしかカウント
されません。呼び出される毎にそれ以前のタイマは無効
となり、引数 0 で呼び出すと以前のタイマをキャン セ
ルして、新しいタイマは始動しません。戻り値は、直前
のタイマの残り時間です。
atan2(Y,X)
Y/X の アークタンジェント を -π から πの範囲で返
します。
bind(SOCKET,NAME)
bind システムコールと同じことをします。成功すれば
真を、失敗すれば偽を返します。 NAME は、ソケットに
合った適切な型の pack されたアドレスでなければなり
ません。プロセス間通信のセクションの例を参照して下
さい。
binmode(FILEHANDLE)
binmode FILEHANDLE
バイナリファイルとテキストファイルを区別するオペレ
ーティングシステム上で、そのファイルを "バイナ リ"
として読み込まれるようにします。バイナリモードで読
み込まれないファイルは、CR LF が入力時に LF に変換
さ れ、 出 力 時には、LF が CR LF に変換されます。
binmode は、UNIX では無効です。 FILEHANDLE が式 の
と き は、値がファイルハンドルの名前として扱われま
す。
caller(EXPR)
caller 現在のサブルーチン呼び出しのコンテキストを返 し ま
す:
($package,$filename,$line) = caller;
EXPRがあると、デバッガがスタックトレースに出力して
使う拡張情報も返します。 EXPRの値は、現在のサブ ル
ーチンの前にいくつの call フレームがあるかを示しま
す。
chdir(EXPR)
chdir EXPR
動作しているディレクトリを、もしできるなら EXPR に
変 更します。 EXPRが省略されると、ホームディレクト
リになります。成功すれば 1 を、失敗すれば 0 を返し
ます。 die の例を参照して下さい。
chmod(LIST)
chmod LIST
ファイルのリストのパーミッションを変更します。リス
トの最初の要素は、数値モードでなければなりません。
成功したファイルの数を返します。
$cnt = chmod 0755, 'foo', 'bar';
chmod 0755, @executables;
chop(LIST)
chop(VARIABLE)
chop VARIABLE
chop 文字列の最後の文字を削り、削られた文字を返します。
基本的には、入力されたレコードの終りから改行文字を
除くために使われますが、文字列のコピーをスキャンす
るわけではないので、s/\n// より効率的です。 VARI
ABLE を省略すると、$_ を chop します。例:
while (<>) {
chop; # 最後のフィールドの \n を除く
@array = split(/:/);
...
}
実際には、代入を含む左辺値のいかなるものも chop で
きます。
chop($cwd = `pwd`);
chop($answer = <STDIN>);
リストを chop するとすべての要素が chop され、最後
に chop された値が返されます。
chown(LIST)
chown LIST
ファイルのリストの所有者 (と所有グループ) を変えま
す。リストの最初の二つの要素は数値で表した uid と
gid がこの順で指定されなければなりません。変更に成
功したファイルの数を返します。
$cnt = chown $uid, $gid, 'foo', 'bar';
chown $uid, $gid, @filenames;
以下は、passwd ファイルから数値でない uid を検索す
る例です:
print "User: ";
$user = <STDIN>;
chop($user);
print "Files: "
$pattern = <STDIN>;
chop($pattern);
open(pass, '/etc/passwd')
|| die "Can't open passwd: $!\n";
while (<pass>) {
($login,$pass,$uid,$gid) = split(/:/);
$uid{$login} = $uid;
$gid{$login} = $gid;
}
@ary = <${pattern}>; # ファイルを得ます
if ($uid{$user} eq '') {
die "$user not in passwd file";
}
else {
chown $uid{$user}, $gid{$user}, @ary;
}
chroot(FILENAME)
chroot FILENAME
同名のシステムコールと同じことをします。これが何を
するのか知らないとしても、気にしない で 下 さ い。
FILENAME を省略すると、$_ に chroot します。
close(FILEHANDLE)
close FILEHANDLE
ファイルハンドルに結びつけられたファイルやパイプを
クローズします。別のファイルをオープンしようとして
い る場合は、FILEHANDLE を閉じる必要がありません。
オープンした際に前のファイルをクローズしてくれるか
らです。 ( open を参照して下さい) しかし、明示的に
入力ファイルのクローズをすると行カウンタ ($.) がリ
セットされるのに対し、 open のときに行なわれる暗黙
のクローズでは、リセットされません。また、後でパイ
プの出力を見たい場合は、パイプをクローズするとパイ
プで起動されたプロセスの完了を待ちます。パイプを明
示的にクローズすると、コマンド情報の戻り値が $? に
入れられます。例:
open(OUTPUT, '|sort >foo'); # sort へパイプ
... # print stuff to output
close OUTPUT; # sort の終了を待ちます
open(INPUT, 'foo'); # sortの結果を得ます
FILEHANDLE は実際のファイルハンドル名を与える式 で
もかまいません。
closedir(DIRHANDLE)
closedir DIRHANDLE
opendir() でオープンされたディレクトリをクローズし
ます。
connect(SOCKET,NAME)
connect システムコールと同じことをします。成功する
と真を、失敗すると偽を返します。 NAME はソケットに
合った適当な型のパッケージアドレスでなければなりま
せん。プロセス間通信のセクションの例を参照して下さ
い。
cos(EXPR)
cos EXPR
EXPR (ラジアンで表現) のコサインを返します。 EXPR
を省略すると $_ のコサインを取ります。
crypt(PLAINTEXT,SALT)
C ラ イ ブ ラリの crypt() 関数と正確に同じように
encrypt された文字列を返します。パスワードファイル
を調べて、粗野なパスワードを見つけるのに便利です。
白い帽子をかぶっている奴だけがこれをしなければなり
ません。
dbmclose(ASSOC_ARRAY)
dbmclose ASSOC_ARRAY
dbm ファイルと連想配列の結び付きを解除します。連想
配列に残っている値は、dbm ファイルのキャッシュに何
が入っているかを知りたいのでなければ、意味がないも
のとなります。この関数は、ndbm を使う場合にのみ 有
用です。
dbmopen(ASSOC,DBNAME,MODE)
dbm や ndbm ファイルと連想配列を結び付けます。
ASSOC は連想配列の名前です。 (通常の open と 違っ
て、最初の引数はファイルハンドルのように見えても、
ファイルハンドル で は* あ り ま せ ん*)。 DBNAME
は、(.dir や .pag の拡張子を除いた) データベースの
名前です。データベースが存在しないと、(umaskで修飾
さ れた) MODE で指定されたプロテクションで作成しま
す。古い dbm 関数しかサポートしないシステムで は、
プ ログラムの中で一つの dbmopen しか許されないかも
しれません。 dbm も ndbm も な い シ ス テ ム で
は、dbmopen 呼び出しは致命的なエラーを生じます。
そ れまでの dbmopen で関連付けられた連想配列の値は
失われます。 dbm ファイルのうち、ある量の値はメ モ
リにキャッシュされます。デフォルトでその量は 64 で
すが、dbmopen の前に連想配列のガーベッジエントリの
数をあらかじめ確保しておくことで、増やすことができ
ます。必要なら、reset コマンドでキャッシュをフラッ
シュすることができます。
dbm ファイルへの書き込み許可を持っていない場合、連
想配列変数を読み出すだけで、それをセットすることは
できません。書き込めるかどうかをテストしたければ、
ファイルテストを使うか、エラーをトラッ プ で き る
eval の中で、ダミーの配列エントリをセットしようと
してみて下さい。
keys() や valuse() のような関数は、大きな dbm ファ
イルを使ったときに、巨大な配列値を返すかもしれませ
ん。大きな dbm ファイルで繰り 返 し を す る と き
は、each() 関数を使った方が良いかもしれません。例:
# 履歴ファイルのオフセットを表示します
dbmopen(HIST,'/usr/lib/news/history',0666);
while (($key,$val) = each %HIST) {
print $key, ' = ', unpack('L',$val), "\n";
}
dbmclose(HIST);
defined(EXPR)
defined EXPR
左辺値 EXPR が、実際に値を持っているかどうかを表す
論理値を返します。多くの演算で、ファイル終端、初期
化されていない変数、システムエラーなどの例外処理条
件 で undefined 値が返されます。この関数は、本当の
ヌル文字列を返すかもしれない操作、特に配列要素を参
照する操作の際に、未定義のヌル文字列と定義されたヌ
ル文字列の判別を可能にします。配列やサブルーチンが
存在するかどうかを調べることもできます。予約済み変
数を使うときは、直観的に期待するような結果になると
は保証されていません。例:
print if defined $switch{'D'};
print "$val\n" while defined($val = pop(@ary));
die "Can't readlink $sym: $!"
unless defined($value = readlink $sym);
eval '@foo = ()' if defined(@foo);
die "No XYZ package defined" unless defined %_XYZ;
sub foo { defined &$bar ? &$bar(@_) : die "No bar"; }
undef も参照して下さい。
delete $ASSOC{KEY}
指定した連想配列から、指定した値を削除します。削除
された値が返りますが、何も削除されなかった場 合 は
undefined 値が返ります。 $ENV{} から削除すると、環
境変数を変更します。 dbm ファイルに結びつけられ た
配列を削除すると、dbm ファイルからその項目を削除し
ます。
以下の例は、連想配列のすべての値を削除します:
foreach $key (keys %ARRAY) {
delete $ARRAY{$key};
}
(しかし、 reset コマンドを使った方が 速 い で しょ
う。undef %ARRAY ならもっと速いでしょう)
die(LIST)
die LIST
eval の外で、LIST の値を STDERR に表示して、そのと
きの $! (errno) の値で終了 (exit) します。 $! が 0
な ら、($? >> 8) (`command` のステータス) の値で終
了します。 ($? >> 8) が 0 なら、255 で終了します。
eval の 中では、エラーメッセージは $@ に詰め込ま
れ、eval は undefined 値で終了します。
同等の例:
die "Can't cd to spool: $!\n"
unless chdir '/usr/spool/news';
chdir '/usr/spool/news' || die "Can't cd to spool: $!\n"
EXPR の値が改行で終らない場合、スクリプトの現在 の
行番号と (もしあれば) 入力行番号が出力され、改行が
加えられます。ヒント: ", stopped" をメッセージに加
え ておくと、 "at foo line 123" が加えられたときに
わかり易くなるので良い で しょ う。 ス ク リ プ ト
"canasta" を走らせているとすると、
die "/etc/games is no good";
die "/etc/games is no good, stopped";
は、多分
/etc/games is no good at canasta line 123.
/etc/games is no good, stopped at canasta line 123.
と出力されます。 exit を参照して下さい。
do BLOCK
BLOCK 内で指定されたうち、最後のコマンドの値を返し
ます。ループ修飾子に修飾されたときは、ループ条件を
テ ストする前に BLOCK が一度実行されます。 (他の文
では、ループ修飾子は、条件を始めにテストします。)
do SUBROUTINE (LIST)
sub で宣言されたサブルーチンを実 行 し、SUBROUTINE
で最後に評価された式の値を返します。その名前のサブ
ルーチンがない場合、致命的エラーを生じます。 (サブ
ル ー チ ン が 存 在しているかどうかを判定したいな
ら、"defined" 演算子を使うのが良いでしょう。) 配列
をリストの一部として渡したいなら、各配列の前に配列
の長さを付けて渡すのが良いでしょう。 (後に出てくる
サ ブ ル ーチンのセクションを参照して下さい。) "do
EXPR" の形との混乱を避けるため、括弧は必要となりま
す。
SUBROUTINE は、一つのスカラ変数でもかまいません。
その場合、実行されるサブルーチン名は、変数から得ら
れます。
別 の (好まれる) 形として、アンパサンド & を前に付
ける &foo(@args) のように、サブルーチンを呼んで も
かまいません。引数を渡さないなら、括弧を使う必要は
ありません。括弧を省略すると、サブルーチンには @_
配列は渡されません。 & 型は、defined や undef 演算
子にサブルーチンを指示するのにも使われます:
if (defined &$var) { &$var($parm); undef &$var; }
do EXPR ファイル名として EXPR の値を使い、 perl スクリプト
として、ファイルの内容を実行します。これは基本的に
perl サブルーチンライブラリからサブルーチンをイ ン
クルードするという使い方をします。
do 'stat.pl';
は、
eval `cat stat.pl`;
とほとんど同じです。違うのは、より効率的で、より簡
潔で、エラーメッセージ中の現在ファイル名は正しく、
カ レントディレクトリに stat.pl がなければ -I で指
定されたライブラリをすべて探すということです。 (予
約 変 数 の セクション中の @INC 配列を参照して下さ
い)。しかし、呼び出しのたびにファイルを解析し直 す
のは同じなので、ループの内側でこのファイルを使うな
ら、起動時間は少し余計にかかるとして も、 -P と
#include を使った方が良いでしょう。 (この #include
を使う問題点は、cpp が # コメントを認識してくれ な
いことです。--逃げ道は、コメント単独として ";#" を
使うことです。) 次のものは等価ではないことに注意し
て下さい:
do $foo; # ファイルを eval します
do $foo(); # サブルーチンを呼びます
ラ イ ブ ラ リ ル ー チ ンのインクルードとしては、
"require" 演算子の方がより良いことを覚えておいて下
さい。
dump LABEL
ただちにコアダンプします。もともと、これは、プログ
ラムの始めにすべての変数を初期化した後にダンプされ
たコアを undump プログラムを使って実行バイナリを作
るためにあります。新しいバイナリが実行 さ れ る と
き、"goto LABEL" を 実 行することから始まります
(goto が受けるすべての制限は適用されます)。コア ダ
ン プで止まったところから、goto で再び始まると考え
れば良いです。 LABEL が省略されると、プログラム は
先頭から再スタートします。警告: ダンプされたときに
open されていたどのファイルも、プログラムが再生 し
たときにはもう open されておらず、perlの側では混乱
する可能性があります。 -u も参照して下さい。
例:
#!/usr/bin/perl
require 'getopt.pl';
require 'stat.pl';
%days = (
'Sun',1,
'Mon',2,
'Tue',3,
'Wed',4,
'Thu',5,
'Fri',6,
'Sat',7);
dump QUICKSTART if $ARGV[0] eq '-d';
QUICKSTART:
do Getopt('f');
each(ASSOC_ARRAY)
each ASSOC_ARRAY
連想配列の次のキーと値の 2 つの要素から成る配列 を
順次返し、それを繰り返すことができます。各エントリ
はランダムのように見える順序で返されます。配列全部
が 読 み 込 ま れ た と き、ヌル配列 (代入されると
FALSE(0) 値となる) が返されます。 そ の 後、 次 の
each() の呼び出しで繰り返しを再び始めます。繰り返
し情報は、配列からすべての要素を読み込むことによっ
てのみリセットできます。繰り返しの間は、配列を変更
してはいけません。各連想配列につき一つずつ繰り返し
情報があり、プログラム中のすべての each(), keys(),
values() 関数呼び出しで共有されます。次の例は、 順
序は異なるものの printenv プログラムのように環境変
数を表示します:
while (($key,$value) = each %ENV) {
print "$key=$value\n";
}
keys() 関数と values() 関数も参照して下さい。
eof(FILEHANDLE)
eof()
eof 次に FILEHANDLE を読んだときファイル終端であるか、
または FILEHANDLE がオープンされていないとき、1 を
返します。 FILEHANDLE は実際のファイルハンドル名を
値に持つ式でもかまいません。 (この関数は、実際には
一文字読み込んでは、ungetc するので、対話的なコ ン
テキストではそれほど有用ではありません。) 引数無し
の eof は、最後に読んだファイルの eof 状態を返しま
す。空の括弧 () は、コマンドラインで指定されたファ
イル群からなる擬似ファイ ル を 指 し ま す。 つ ま
り、eof() は while (<>) の内側で最後のファイルの終
端を検出するときに意味があります。 while (<>) ルー
プの中で各ファイルを調べたいときは、eof(ARGV) また
は括弧のない eof を使って下さい。例:
# 最後のファイルの最終行の直前にダッシュを挿入します
while (<>) {
if (eof()) {
print "--------------\n";
}
print;
}
# 各入力ファイル毎に、行番号をリセットします
while (<>) {
print "$.\t$_";
if (eof) { # Not eof().
close(ARGV);
}
}
eval(EXPR)
eval EXPR
eval BLOCK
EXPR は解析され、一つの小さな perl プログラムで あ
るかのように実行されます。 perl プログラムのコンテ
キストの中で実行されるので、どの変数設定、サブルー
チ ン、 フォーマット定義もその後に残ります。戻り値
は、丁度サブルーチンと同様に、最後に評価された式が
返ります。文法エラーや実行時エラーがあるか、die 文
があれば、eval により undefined が返り、$@ にエ ラ
ー メッ セージがセットされます。もしエラーがなけれ
ば、$@ はヌル文字列であることが保証されます。 EXPR
を 省略すると、$_ を評価します。最後のセミコロンは
どれも式から除かれます。
eval はしかし、致命的エラーまでトラップするの で、
(dbmopen や symlinkのような) ある機能が実装されて
いるかどうかを決めるには便利なことを覚えておいて下
さ い。 die 演算子が例外を起こすように使われるの
は、perl の例外トラップ機構でもあります。
実行されるコードが変わらないなら、その度に再コンパ
イルされる時間を費すよりは、実行時エラーをトラップ
する eval-BLOCK の形をとった方が良いかもしれ ま せ
ん。どんなエラーも起これば $@ にメッセージが返りま
す。 EXPR のような、シングルクォートされた文字列を
評 価すると、同じ効果がありますが、eval-BLOCK の形
ではコンパイル時に文法エラーを報 告 す る の に 対
し、eval-EXPR の形では $@ を通して実行時に文法エラ
ーを報告する点が異なります。 eval-EXPR の形は、 最
初 に 成功したときに eval-BLOCK に最適化されます。
(e 修飾子を使った場合、置換される側はシングル クォ
ー ト された文字列とみなされ、同じ最適化が起こりま
す。) 例:
# 0 除算を致命的エラーにしません
eval { $answer = $a / $b; }; warn $@ if $@;
# 初回使用後、同じものに最適化されます。
eval '$answer = $a / $b'; warn $@ if $@;
# コンパイル時エラー
eval { $answer = };
# 実行時エラー
eval '$answer ='; # sets $@
exec(LIST)
exec LIST
LIST の中に一つ以上の引数があるか、LIST が一つ以上
の 値 を 持 つ 配 列 な らば、リストの引数を付けて
execvp() を呼びます。一つのスカラ引数だけなら、 引
数 に シェルのメタキャラクタがあるかどうかを調べま
す。あれば、解析のために引数を丸ごと "/bin/sh -c"
に 渡 し、 無 け れ ば、 引 数 は 単 語に split さ
れ、execvp() に直接渡されます。その方が効率が良 い
か らです。注意: exec (と system) は出力バッファを
フラッシュしないので、出力が失われるのを避けるため
に $| をセットする必要があるかもしれません。例:
exec '/bin/echo', 'Your arguments are: ', @ARGV;
exec "sort $outfile | uniq";
もし、最初の引数を本当に実行したいのでなく、実行し
ようとしているプログラムの名前を詐称したいだ け な
ら、 本 当 に 走らせたいプログラムを変数に割り当て
て、LIST の前に変数の名前をコンマを付けずに置く よ
うに指定できます。 (これは、たとえ単一スカラしかリ
ストに無くても、常に多くの値を持つリス ト と し て
LIST の解釈を強制します。) 例:
$shell = '/bin/csh';
exec $shell '-sh'; # ログインシェルのふりをします
exit(EXPR)
exit EXPR
EXPR を評価し、ただちにその値で終了します。例:
$ans = <STDIN>;
exit 0 if $ans =~ /^[Xx]/;
die を参照して下さい。 EXPR が省略されると、値 0
の状態で終了します。
exp(EXPR)
exp EXPR
e の EXPR 乗を返 し ま す。 EXPR を 省 略 す る
と、exp($_) を返します。
fcntl(FILEHANDLE,FUNCTION,SCALAR)
fcntl(2) 関 数の実装です。正しい関数定義を得るに
は、多分
require "fcntl.ph"; # 多分 /usr/local/lib/perl/fcntl.ph
を始めに書いておかなければならない で しょ う。 も
し、fcntl.ph が存在しないか、もしくは正しい定義が
されていない場合、 <sys/fcntl.h> のような C のヘッ
ダファイルに基づいて、自分で何とかしなければなりま
せん。 (perl kit から来る h2ph と呼ばれる perl ス
クリプトがあり、このことを助けてくれるでしょう) 引
数の処理と戻り値を返すことは、この後に書かれている
ioctl のように動作します。 fcntl は、fcntl(2) が実
装されていないマシンで使われると致命的エラーを生じ
ます。
fileno(FILEHANDLE)
fileno FILEHANDLE
ファイルハンドルに対するファイル記述子を返します。
select() のビットマップを構成するのに便 利 で す。
FILEHANDLE が式だと、その値がファイルハンドルの名
前と解釈されます。
flock(FILEHANDLE,OPERATION)
ファイルハンドルに対し flock(2) を呼びます。 OPER
ATION の定義については、flock(2) のマニュアルを参
照して下さい。成功すれば真を、失敗すれば偽を返しま
す。 flock(2) が実装されていないマシンで使うと、致
命的エラーになります。以下は、BSD システムのメール
ボックスにメールを追加します。
$LOCK_SH = 1;
$LOCK_EX = 2;
$LOCK_NB = 4;
$LOCK_UN = 8;
sub lock {
flock(MBOX,$LOCK_EX);
# 待っている間に、他の誰かが追加する
# 場合のために...
seek(MBOX, 0, 2);
}
sub unlock {
flock(MBOX,$LOCK_UN);
}
open(MBOX, ">>/usr/spool/mail/$ENV{'USER'}")
|| die "Can't open mailbox: $!";
do lock();
print MBOX $msg,"\n\n";
do unlock();
fork fork() システムコールを実行します。親プロセスに子
の pid を返し、子プロセスには 0 を返します。注 意:
フラッシュされていないバッファは、両方のプロセスで
フラッシュされずに残ります。これは二重出力を避ける
た めに、$| をセットする必要があるかもしれないとい
うことを意味します。
getc(FILEHANDLE)
getc FILEHANDLE
getc FILEHANDLE に結びつけられた入力ファイルから、次 の
文字を返します。 EOF ではヌルを返します。 FILEHAN
DLE を省略すると、STDIN から読み込みます。
getlogin
現在のログイン状況が /etc/utmp から得られれば、 そ
れ を返します。得られなければ、getpwuid を使って下
さい。
$login = getlogin || (getpwuid($<))[0] ||
"Somebody";
getpeername(SOCKET)
SOCKET 接続の向こう側の pack された sockaddr アド
レスを返します。
# 内部 sockaddr
$sockaddr = 'S n a4 x8';
$hersockaddr = getpeername(S);
($family, $port, $heraddr) =
unpack($sockaddr,$hersockaddr);
getpgrp(PID)
getpgrp PID
指定された PID に対する現在のプロセスグループを 返
し ます。現在のプロセスでは 0 です。 getpgrp(2) が
実装されていないマシンで使うと、致命的エラーになり
ます。 EXPR が省略されると、現在のプロセスのプロセ
スグループが返ります。
getppid 親プロセスのプロセス ID を返します。
getpriority(WHICH,WHO)
プロセス、プロセスグループ、ユーザの現在のプライオ
リ ティ を返します。 (getpriority(2)を参照して下さ
い。) getpriority(2) を実装していないマシンで使 う
と致命的エラーになります。
getpwnam(NAME)
getgrnam(NAME)
gethostbyname(NAME)
getnetbyname(NAME)
getprotobyname(NAME)
getpwuid(UID)
getgrgid(GID)
getservbyname(NAME,PROTO)
gethostbyaddr(ADDR,ADDRTYPE)
getnetbyaddr(ADDR,ADDRTYPE)
getprotobynumber(NUMBER)
getservbyport(PORT,PROTO)
getpwent
getgrent
gethostent
getnetent
getprotoent
getservent
setpwent
setgrent
sethostent(STAYOPEN)
setnetent(STAYOPEN)
setprotoent(STAYOPEN)
setservent(STAYOPEN)
endpwent
endgrent
endhostent
endnetent
endprotoent
endservent
これらのルーチンは、システムライブラリ中の同名の関
数を実行します。配列のコンテキストの中では、これら
の各 get ルーチンの戻り値は、以下のようになります:
($name,$passwd,$uid,$gid,
$quota,$comment,$gcos,$dir,$shell) = getpw...
($name,$passwd,$gid,$members) = getgr...
($name,$aliases,$addrtype,$length,@addrs) = gethost...
($name,$aliases,$addrtype,$net) = getnet...
($name,$aliases,$proto) = getproto...
($name,$aliases,$port,$proto) = getserv...
(もしエントリが存在しなければ、ヌルリストになり ま
す。)
スカラのコンテキストでは、 name による検索でない場
合には name が得られ、 name による検索の場合 に は
name 以外が得られます。 (エントリが存在しない場合
は、undefined 値となります。) 例:
$uid = getpwnam
$name = getpwuid
$name = getpwent
$gid = getgrnam
$name = getgrgid
$name = getgrent
他
getgr... の返す $menbers 値は、空白で区切られた グ
ループメンバのログイン名のリストです。
gethost... 関数では、h_errno 変数が C でサポートさ
れていれば、関数のコールが失敗したとき $? を介して
返されます。成功した関数コールの返す @addrs 値は、
相当するシステムライブラリ呼び出しに返され た raw
address の リ ス ト です。インターネットドメイン
(INET) では、各アドレスは 4 バイト長で以下のように
書くと unpack できます。
($a,$b,$c,$d) = unpack('C4',$addr[0]);
getsockname(SOCKET)
pack された、SOCKET接続のこちら側の sockaddr アド
レスを返します。
# An internet sockaddr
$sockaddr = 'S n a4 x8';
$mysockaddr = getsockname(S);
($family, $port, $myaddr) =
unpack($sockaddr,$mysockaddr);
getsockopt(SOCKET,LEVEL,OPTNAME)
要求したソケットのオプションを返します。エラーの場
合は undefined を返します。
gmtime(EXPR)
gmtime EXPR
time 関数に返された時刻を、Greenwich timezone とし
て 9 要素の配列に変換します。通常は次のように使 い
ます:
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
gmtime(time);
すべての配列要素は数値で、構造体 tm から直接得られ
るものです。これにより $mon は 0..11 の 範 囲 で
$wday は 0..6 の範囲であることになります。 EXPR を
省略すると、gmtime(time) を実行します。
goto LABEL
LABEL というラベルを付けられた文を探し、そこから実
行を再開します。現在のところ、プログラムの本体内で
do {} 構造の内側が入れ子になっていない文にしか行け
ま せん。この文は効率的には実装されておらず、 se_d
to-perl 翻訳プログラムを簡単にできるようにするため
だ けあります。翻訳された sed スクリプトの一貫性の
サポートはしますが、このセマンティックスを私がいつ
変 更 するかわからないので、自らの責任で使って下さ
い。全く使わない方が良いでしょう。
grep(EXPR,LIST)
LIST の各要素に対して (ローカルには各要素を $_ に
セット)、EXPR を評価して、式が真であると評価された
要素だけからなる配列を返します。スカラのコンテキス
トでは、式が真になった回数を数値で返します。
@foo = grep(!/^#/, @bar); # コメントを除きます
$_ は配列値への参照なので、配列の要素を変更する場
合に使えることを覚えておきましょう。これは便利です
が、LIST が名前のついた配列でないと、おかしな結果
を引き起こすことになります。
hex(EXPR)
hex EXPR
10 進値 EXPR を 16 進文字列にして返します。 (0 ま
たは 0x で始まる文字列を解釈するなら、oct() を参照
して下さい。) EXPR を省略すると $_ を使います。
index(STR,SUBSTR,POSITION)
index(STR,SUBSTR)
STR の中で、POSITION かそれ以降に最初に SUBSTR が
現れる位置を返します。 POSITION を省略すると、文字
列の先頭から検索します。戻り値は、0 か $[ 変数に設
定されたものがベースになります。 SUBSTR がみつから
ないと、ベースから 1 を引いた値を返し、通常 -1 に
なります。
int(EXPR)
int EXPR
EXPR の整数部を返します。 EXPR が省略されると、$_
を使います。
ioctl(FILEHANDLE,FUNCTION,SCALAR)
これは、ioctl(2) 関数を実装しています。正しい関 数
定義を得るには、多分始めの方で
require "ioctl.ph"; # 多分 /usr/local/lib/perl/ioctl.ph
と書かなければならないでしょう。 ioctl.ph が存在し
ないか、または正しく定義 さ れ て い な い 場 合、
<sys/ioctl.h> のような C のヘッダファイルから自分
自身でなんとかしなければなりません。 (perl キッ ト
にある h2ph というスクリプトがこの助けになるでしょ
う。) SCALAR は、FUNCTIONに依存して、参照または 書
き 込みがされます。 FUNCTION --SCALAR の文字列値へ
のポインタは、実際の ioctl 呼び出しの第 3 引数に渡
さ れます。 (SCALAR が文字列値でなく数値であった場
合、文字列値へのポインタでなく数値そのものが渡され
ます。これが真であることを保証するには、このスカラ
を使う前に 0 を加えて下さい。) ioctl() に使われ る
構 造体の値を扱うには、pack() 関数と unpack() 関数
が便利です。次の例は、DEL に erase 文字をセット し
ます。
require 'ioctl.ph';
$sgttyb_t = "ccccs"; # chars 4 個と short 1 個
if (ioctl(STDIN,$TIOCGETP,$sgttyb)) {
@ary = unpack($sgttyb_t,$sgttyb);
$ary[2] = 127;
$sgttyb = pack($sgttyb_t,@ary);
ioctl(STDIN,$TIOCSETP,$sgttyb)
|| die "Can't ioctl: $!";
}
ioctl (と fcntl) の戻り値は以下の通りです:
OS の戻り値: perlの戻り値:
-1 undefined 値
0 文字列 "0 but true"
それ以外 その数
こ のように、perl は成功時に真を、失敗時に偽を返し
ますが、オペレーティングシステムから返される実際の
値も簡単に判定することができます:
($retval = ioctl(...)) || ($retval = -1);
printf "System returned %d\n", $retval;
join(EXPR,LIST)
join(EXPR,ARRAY)
分 割されている LIST や ARRAY の文字列を、フィール
ドセパレータとして値 EXPR をはさんだ一つの文字列に
つなげて、その文字列を返します。例:
$_ = join(':',
$login,$passwd,$uid,$gid,$gcos,$home,$shell);
split を参照して下さい。
keys(ASSOC_ARRAY)
keys ASSOC_ARRAY
名前のついた連想配列のすべてのキーからなる普通の配
列を返します。キーは、見かけ上ランダムな順で返され
ま すが、values() 関数や each() 関数 (これによって
連想配列は変更されません) が生成するものと同じ順に
なります。以下は、環境変数を表示する別の方法です:
@keys = keys %ENV;
@values = values %ENV;
while ($#keys >= 0) {
print pop(@keys), '=', pop(@values), "\n";
}
キーでソートすると:
foreach $key (sort(keys %ENV)) {
print $key, '=', $ENV{$key}, "\n";
}
kill(LIST)
kill LIST
プロセスのリストにシグナルを送ります。リストの最初
の要素は、送られるシグナルでなければなりません。シ
グナル送信に成功したプロセスの数を返します。
$cnt = kill 1, $child1, $child2;
kill 9, @goners;
シグナルが負の場合、プロセスの代わりにプロセスグル
ープを kill します。 (System Vでは、負の プロセ ス
番号はプロセスグループも kill しますが、互換性はあ
りません。) クォートでくくられたシグナル名も使えま
す。
last LABEL
last last コマンドは、(ループ内で使われるような) C の
break 文に似ていて、該当するループを直ちに終了しま
す。 LABEL が省略されると、このコマンドは最も内側
のループを抜けます。 continue ブロックがあったとし
ても、実行されません:
line: while (<STDIN>) {
last line if /^$/; # ヘッダが終ったら抜けます
...
}
length(EXPR)
length EXPR
EXPR の 値の文字列長を返します。 EXPR を省略する
と、$_ の長さを返します。
link(OLDFILE,NEWFILE)
OLDFILE にリンクされた NEWFILE を作成します。成 功
すると 1 を、失敗すると 0 を返します。
listen(SOCKET,QUEUESIZE)
listen システムコールと同じことを行ないます。成功
すると真を、失敗すると偽を返します。プロセス間通信
のセクションの例を参照して下さい。
local(LIST)
閉 じたブロック、サブルーチン、eval、"do" に局所的
な変数リストを宣言します。リストされたすべての要素
は左辺値として妥当なものでなければなりません。この
演算子は、LIST 内のその時点での変数を隠れたス タッ
クに保存し、ブロックやサブルーチンや eval を抜ける
ときに戻すように動作します。これは、呼ばれたサブル
ーチンもグローバル変数でなく、ローカル変数を参照す
ることを意味します。そうしたければ、LIST に代入 し
てローカル変数を初期化してもかまいません。 (初期値
が特定の値として与えられていなければ、undefined 値
として生成されます。) 普通、これはサブルーチンのパ
ラメータに名前をつけるのに使われます。例:
sub RANGEVAL {
local($min, $max, $thunk) = @_;
local($result) = '';
local($i);
# 多分 $thunk は $i を参照しています
for ($i = $min; $i < $max; $i++) {
$result .= eval $thunk;
}
$result;
}
if ($sw eq '-v') {
# グローバルな配列でローカルな配列を初期化します
local(@ARGV) = @ARGV;
unshift(@ARGV,'echo');
system @ARGV;
}
# @ARGV が元に戻されます
# 一時的に digits という連想配列に追加をしています。
if ($base12) {
# (注意: これが効率的と言いたいわけではありません)
local(%digits) = (%digits,'t',10,'e',11);
do parse_num();
}
local() は実行時のコマンドで、ループ終了時に全部を
一度に解放するまでは、ループを通るたびに実行され、
毎回スタックを消費していきます。
localtime(EXPR)
localtime EXPR
time 関数に返された時刻を、ローカルタイムゾーン と
し て解析された 9 要素の配列に変換します。通常次の
ように使われます:
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime(time);
すべての配列要素は数字で、構造体 tm から直接得られ
た も の で す。 これにより $mon は 0..11 の範囲で
$wday は 0..6 の範囲であることになります。 EXPR を
省略すると、localtime(time) を実行します。
log(EXPR)
log EXPR
EXPR の (底が e の) 対数を返します。 EXPR を省略す
ると、$_ の log を返します。
lstat(FILEHANDLE)
lstat FILEHANDLE
lstat(EXPR)
lstat SCALARVARIABLE
stat() 関数と同じことを実行しますが、シンボリッ ク
リ ン クでは指している先のファイルの代わりにシンボ
リックリンク自身の状態を返します。シンボリックリン
クが実装されていないシステムでは、通常の stat を実
行します。
m/PATTERN/gio
/PATTERN/gio
パターンマッチに合う文字列を検索し、真 (1) か 偽
('') を返します。 =~ や !~ を介した文字列の指定が
なければ、文字列 $_ が検索されます。 (=~ で指定 さ
れた文字列は、左辺値である必要はありません。式の評
価結果でもかまいませんが、=~ はどちらかというと 優
先度が高いことを覚えておいて下さい。) 正規表現のセ
クションを参照して下さい。
/ が区切り文字である場合、始めの 'm' は省略可能 で
す。'm' があると、英数字以外のどの文字でも区切りに
できます。これは、特に '/' を含む UNIX のパス名 へ
のマッチに便利です。最後の区切りの後にオプション文
字 'i' が続くと、マッチングが大文字小文字の区別 な
く 行なわれます。 PATTERN は、スカラ変数への参照を
含んでいてもよく、それはパターン検索が評価される毎
に 挿入されます (パターンはリコンパイルされます)。
( $) と $| は文字列終端のテストに見えるため、挿 入
は行なわれません。) パターンを一度だけコンパイルさ
せたい場合は、後ろの区切り文字の後に "o" を加え て
下さい。これにより、余分な実行時再コンパイルを避け
られるので、挿入したい値がスクリプトの動いている間
中、 変わらないときには便利です。 PATTERN がヌル文
字に評価されたときは、最後に成功した正規表現が代わ
りに使われます。
配 列 値が必要なコンテキストで使われると、パターン
マッチはパターンの中でマッチした subexpression を
括弧でくくったものすなわち、 ($1, $2, $3...) から
なる配列を返します。この場合、実際には $1, $2 等を
セッ ト は* せず*、 $+, $`, $&, $' もセットしませ
ん。マッチが失敗すると、ヌル配列が返ります。マッチ
が成功しても括弧がないと、配列値 (1) が返ります。
例:
open(tty, '/dev/tty');
<tty> =~ /^y/i && do foo(); # y なら foo を実行
if (/Version: *([0-9.]*)/) { $version = $1; }
next if m#^/usr/spool/uucp#;
# 恵まれない人の grep
$arg = shift;
while (<>) {
print if /$arg/o; # 一度だけコンパイル
}
if (($F1, $F2, $Etc) = ($foo =~ /^(\S+)\s+(\S+)\s*(.*)/))
こ の 最 後の例は、$foo を最初の二語と残りに split
し、三つのフィールドを $F1、$F2、$Etc に代入 し ま
す。どれかの変数が代入された場合、すなわちパターン
がマッチした場合、この条件は真となります。
"g" 修飾子は、グローバルパターンマッチの指定です--
つまり、文字列の中でできるだけ多くのマッチを行ない
ます。どのように振舞うかは、コンテキストに依存しま
す。配列のコンテキストでは、正規表現の中ですべての
括弧にマッチした文字列のリストを返します。括弧がな
ければ、パターン全体を囲む括弧があるかのようにマッ
チした文字列すべてのリストを返します。スカラのコン
テキストでは、文字列を通してマッチする毎に*真*を返
し、マッチしなかったとき*偽*を返します。 (言いかえ
ると、最後にテストした場所を覚えていて、そこから再
び検索を始めるということです。) 最後のマッチから文
字列が変更されていないことを仮定しています。マッチ
とマッチの間で文字列を変更することは、未定義な動作
を 引き起こすかもしれません。 (実際には substr()を
使って、全文字列の長さを変えずにその場で変更するな
ら、できます。しかし、一般にはそういう変更は s///g
を使うべきです。) 例:
# 配列のコンテキスト
($one,$five,$fifteen) = (`uptime` =~ /(\d+\.\d+)/g);
# スカラのコンテキスト
$/ = ""; $* = 1;
while ($paragraph = <>) {
while ($paragraph =~ /[a-z]['")]*[.!?]+['")]*\s/g) {
$sentences++;
}
}
print "$sentences\n";
mkdir(FILENAME,MODE)
FILENAME で指定されたディレクトリを、(umask で修飾
さ れた) MODE で指定されたパーミッションで作成しま
す。成功すると 1 を、失敗する と 0 を 返 し、$!
(errno) をセットします。
msgctl(ID,CMD,ARG)
System V IPC 関数の msgctl を呼びます。 CMD が
&IPC_STAT なら、ARG は返された msqid_ds 構造を保持
す る変数でなければなりません。 ioctl のように、エ
ラーのときは undefined 値を、0 のときには "0 but
true" を、でなければ実際の戻り値を返します。
msgget(KEY,FLAGS)
System V IPC 関数の msgget を呼びます。成功時は
メッセージキュー ID を、エラーが起これば undefined
value を返します。
msgsnd(ID,MSG,FLAGS)
System V IPC 関数の msgsnd を呼び、メッセージ MSGS
をメッセージキュ ー ID に 送 信 し ま す。 MSG
は、pack("L", $type) で作られる long integer の
メッセージ型で始めなければなりません。成功すれば真
を、エラーが起こると偽を返します。
msgrcv(ID,VAR,SIZE,TYPE,FLAGS)
System V IPC 関数 msgrcv を呼び、メッセージキュー
ID からメッセージを受け取り、最大メッセージサイ ズ
SIZE で変数 VAR に格納します。メッセージを受け取る
と、VAR に最初に格納されたものがメッセージ型 と な
り、VAR の最大長は、SIZE にメッセージ型のサイズを
加えたものになることに注意して下さい。成功すると真
を、エラーでは偽を返します。
next LABEL
next next コマンドは、C の continue 文と同様に、ループ
の次の繰り返しを始めます。
line: while (<STDIN>) {
next line if /^#/; # コメントを捨てます
...
}
上の例で continue ブロックがあると、行が捨てられた
場合でも実行されることを覚えておいて下さい。 LABEL
が省略されると、このコマンドは最も内側のループを続
けます。
oct(EXPR)
oct EXPR
10 進数 EXPR を、8 進文字列にして返します。 (EXPR
が 0x で始まる文字列なら、10 進の代わりに 16 進 と
して変換します。) 以下は、10 進、8 進、16 進の標準
的な記法を扱います。
$val = oct($val) if $val =~ /^0/;
EXPR が省略されると、$_ を使います。
open(FILEHANDLE,EXPR)
open(FILEHANDLE)
open FILEHANDLE
EXPR で与えられたファイル名のファイルをオ ー プ ン
し、FILEHANDLE に結びつけます。 FILEHANDLE が式の
場合、その値を実際にファイルハンドルが求める名前と
し て使います。 EXPR が省略されると、FILEHANDLE と
同名のスカラ変数が保持する値がファイル名とな り ま
す。 ファイル名の前に "<" を付けるか、何も付けない
場合、ファイルは入力用にオープンされます。ファイル
名 が ">" で始まると、ファイルは出力用にオープンさ
れます。ファイル名が ">>" で始まると、ファイルは追
加 書き込み用にオープンされます。 ('>' や '<' の前
に '+' を付けると、ファイルを読み書き両用にでき ま
す。) ファイル名が "|" で始まると、ファイル名は出
力がパイプされるコマンドと解釈され、ファイル 名 が
"|" で終ると、入力がパイプされるコマンドと解釈され
ます。 (入出力共パイプするコマンドは必要がな い で
しょう。) '-' をオープンすると STDIN を、'>-' をオ
ープンすると STDOUT をオープンします。 open は成功
し たとき、0 でない値を、失敗したとき undefined 値
を返します。 open がパイプを含む場合、戻り値はサブ
プロセスの pid となります。例:
$article = 100;
open article || die "Can't find article $article: $!\n";
while (<article>) {...
open(LOG, '>>/usr/spool/news/twitlog');
# (ログ保存)
open(article, "caesar <$article |");
# 記事を decrypt
open(extract, "|sort >/tmp/Tmp$$");
# $$ は現在のプロセス
# 引数リストのファイルを、それがインクルードするものも
# 含めて処理します
foreach $file (@ARGV) {
do process($file, 'fh00'); # no pun intended
}
sub process {
local($filename, $input) = @_;
$input++; # 文字列インクリメント
unless (open($input, $filename)) {
print STDERR "Can't open $filename: $!\n";
return;
}
while (<$input>) { # 間接指定に注意
if (/^#include "(.*)"/) {
do process($1, $input);
next;
}
... # 続く
}
}
Bourne shell の慣習により、EXPR は ">&" で始めるよ
うな指定もできます。その場合、文字列の残りはファイ
ルハンドル (数字ならファイル記述子) の名前と解釈さ
れ、dup して open します。 >>, <, +>, +>>, +< の後
に & を使ってもかまいません。指定するモードは、元
のファイルハンドルのモードと一致していなくてはなり
ません。以下は、 STDOUT と STDERR を保存し、リダイ
レクトを行なって、その後で書き戻します:
#!/usr/bin/perl
open(SAVEOUT, ">&STDOUT");
open(SAVEERR, ">&STDERR");
open(STDOUT, ">foo.out") || die "Can't redirect stdout";
open(STDERR, ">&STDOUT") || die "Can't dup stdout";
select(STDERR); $| = 1; # バッファリングしません
select(STDOUT); $| = 1; # バッファリングしません
print STDOUT "stdout 1\n"; # これもサブプロセスで
print STDERR "stderr 1\n"; # 動作します
close(STDOUT);
close(STDERR);
open(STDOUT, ">&SAVEOUT");
open(STDERR, ">&SAVEERR");
print STDOUT "stdout 2\n";
print STDERR "stderr 2\n";
コマンド "-" でパイプをオープンする、すなわち "|-"
や "-|" を オープンすると、暗黙のうちに fork さ
れ、open の戻り値として親プロセスには、子プロセ ス
の pid が返され、子プロセスには 0 が返されます。
(open が成功したかどうかは、defined($pid) を使って
判断して下さい。) ファイルハンドルは、親にとって普
通の挙動をしますが、子には STDOUT/STDIN にパイプさ
れ たファイルハンドルの i/o となります。子プロセス
でファイルハンドルがオープンされず、--新しくファイ
ル ハンドルは、新しい STDIN から STDOUT へのパイプ
となります。よく使われるのは、普通のパイプのオープ
ンと同様、パイプコマンドの実行状態をコントロールし
たいとき、setuid されたプログラムを走らせると き、
シェルコマンドでメタキャラクタのチェックをする必要
がないときです。次の二つは、それぞれある程度同等で
す:
open(FOO, "|tr '[a-z]' '[A-Z]'");
open(FOO, "|-") || exec 'tr', '[a-z]', '[A-Z]';
open(FOO, "cat -n '$file'|");
open(FOO, "-|") || exec 'cat', '-n', $file;
パ イプされたファイルハンドルを明示的に close する
と、親プロセスは子プロセスが終了するのを待つことに
な り、$? に状態を返します。 fork を行う操作では、
両方のプロセスでフラッシュされないバッファがそのま
ま残ることに注意して下さい。これは、二重出力を避け
るために $| をセットした方が良いことを意味します。
open に渡されたファイル名は、前後の空白が除かれま
す。意図的に変な文字を含むファイル名を持つファイル
をオープンしたいときは、前後の空白もこのように守っ
てやる必要があります:
$file =~ s#^(\s)#./$1#;
open(FOO, "< $file\0");
opendir(DIRHANDLE,EXPR)
EXPR という名前 の ディ レ ク ト リ を readdir(),
telldir(), seekdir(), rewinddir(), closedir() で
処理できるようにオープンします。成功すると真を返し
ます。 DIRHANDLE は、FILEHANDLE とは別個のそれ自身
の名前空間を持ちます。
ord(EXPR)
ord EXPR
EXPR の最初の文字のアスキー値を数値で返 し ま す。
EXPR が省略されると、$_ を使います。
pack(TEMPLATE,LIST)
配列または値のリストを引数に取り、バイナリ構造体に
パックし、構造体を含む文字列を返します。 TEMPLATE
は値の順序と型を与える文字のシークエンスで、以下の
ようになります:
A アスキー文字列(スペースが padding される)
a アスキー文字列(ヌルが padding される)
c signed char
C unsigned char
s signed short
S unsigned short
i signed integer
I unsigned integer
l signed long
L unsigned long
n short ("network" order)
N long ("network" order)
f 単精度浮動小数点 (native format)
d 倍精度浮動小数点 (native format)
p 文字列へのポインタ
v short ("VAX" (little-endian) order)
V long ("VAX" (little-endian) order)
x null byte
X Back up a byte
@ 絶対位置にまでヌルで埋める
u uuencode された文字列
b ビット文字列 (vec()のような昇順).
B ビット文字列 (降順).
h 16 進文字列 (低 nybble が先).
H 16 進文字列 (高 nybble が先).
どの文字も繰り返し回数を表す数を続けることができま
す。 "a", "A", "b", "B", "h", "H" 以外の型で
は、pack 関数は LIST から回数を指定された数だけ 値
を 取ります。繰り返し数として * を使うと、残りすべ
ての分だけ繰り返します。 "a" と "A" の型は値一つし
か 取りませんが、繰り返し指定を文字列長として pack
するので、ヌルや空白での padding が必要に な り ま
す。 (unpack するときは、"A" は、後に続く空白を削
りますが、"a" はしません。) 同様 に、"b" と "B"
フィールドは、指定したビット長を pack します。 "h"
と "H" フィールドは、指定した長さの nybbles をパッ
ク します。実数 (float と double) は、そのマシンの
機械語フォーマットのみです。浮動小数点フォーマット
関 係 の 多様性と標準の "network" 表現が無いことか
ら、交換することはできません。これは、あるマシンで
pack された浮動小数点データは、他のマシンでは、た
とえ両方が IEEE 浮動小数点数演算を行っていても (メ
モ リ表現の endian は IEEE の仕様には無いから)、読
めないかもしれないということを意味し ま す。 perl
は、 す べての数値計算を内部的には double を用い、
double -> float -> double という変換は精度を失うだ
ろ う と い う こ と に 注 意 し て 下さい (すなわ
ち、unpack("f",pack("f", $foo)) は一般に $foo には
なりません)。
例:
$foo = pack("cccc",65,66,67,68);
# foo は "ABCD"
$foo = pack("c4",65,66,67,68);
# 上と同じ
$foo = pack("ccxxcc",65,66,67,68);
# foo は "AB\0\0CD"
$foo = pack("s2",1,2);
# little-endian の "\1\0\2\0"
# big-endian の "\0\1\0\2"
$foo = pack("a4","abcd","x","y","z");
# "abcd"
$foo = pack("aaaa","abcd","x","y","z");
# "axyz"
$foo = pack("a14","abcdefg");
# "abcdefg\0\0\0\0\0\0\0"
$foo = pack("i9pl", gmtime);
# 実際の tm 構造体 (少なくとも私のシステムでは)
sub bintodec {
unpack("N", pack("B32", substr("0" x 32 . shift, -32)));
}
一 般 に unpack 関数でも同じテンプレートが使われま
す。
pipe(READHANDLE,WRITEHANDLE)
相当するシステムコールのように一対の接続されたパイ
プをオープンします。パイプでつながったプロセスのル
ープを設定するときは、注意深くしないとデッドロック
を起こすことがあることに気をつけて下さい。それに加
えて、perl のパイプは標準入力のバッファリングを 使
う ので、アプリケーションに依っては、$| をセットし
てコマンド毎に WRITEHANDLE をフラッシュする必要 が
あるかもしれません。 [perl バージョン 3.0 パッチレ
ベル 9 以上が必要]
pop(ARRAY)
pop ARRAY
配列の最後の値を取り出し、配列の長さを 1 だけ短 く
します。
$tmp = $ARRAY[$#ARRAY--];
同 じ結果となります。配列に要素がない場合は、unde
fined 値を返します。
print(FILEHANDLE LIST)
print(LIST)
print FILEHANDLE LIST
print LIST
print 文字列または、コンマ区切りの文字列のリストを表示し
ま す。 成 功すると、0 以外を返します。 FILEHANDLE
は、ファイルハンドルの名前を保持したスカラ変数名で
も かまいません。これにより 1 レベルの間接指定がで
きます。 (注意: FILEHANDLE が変数で次のトークン が
項の場合、+ を挿入するか引数に括弧を付けないと、演
算子として解釈の間違いをするかも し れ ま せ ん。)
FILEHANDLE が省略されると、デフォルトで標準出力 (
または最後に select された出力チャネル-- select()
を参照して下さい) に出力します。 LIST が省略される
と、$_ を STDOUT に出力します。デフォルト出力 チャ
ネ ルを STDOUT 以外に設定するには、select 演算子を
使って下さい。 print は LIST を取るので、LIST の中
のものは何でも配列のコンテキストで評価され、サブル
ーチン呼び出しなら配列のコンテキストで評価された式
を 持 つ こ と に な る のを覚えておきましょう。ま
た、print キーワードの後に左括弧を置くときは、対応
する右括弧が print の引数の終りを示す --すなわち +
を挿入するか、括弧をすべての引数に付けるのでなけれ
ば、左括弧を置いてはいけません。
printf(FILEHANDLE LIST)
printf(LIST)
printf FILEHANDLE LIST
printf LIST
"print FILEHANDLE sprintf(LIST)" と同等です。
push(ARRAY,LIST)
ARRAY (@ は省略可能) をスタックとして扱い、LIST の
値を ARRAY の終りに追加しま す。 ARRAY の 長 さ
は、LIST の長さだけ増えます。これは、以下と同じこ
とになります。
for $value (LIST) {
$ARRAY[++$#ARRAY] = $value;
}
が、より効率的です。
q/STRING/
qq/STRING/
qx/STRING/
これは、実際には関数ではありませんが、クォートされ
た文字列にバックスラッシュをたくさん置き過ぎるのを
避けるための、単なる簡略記法です。 q 演算子はシ ン
グ ルクォートを生成し、qq 演算子はダブルクォートを
生成します。 qx 演算子は、バッククォートを生成しま
す。英数字でない文字なら、改行を含めて何でも、/ の
代わりに区切り文字にできます。区切りが ( か { な
ら、終了の区切りは、対応する ) か } になります。 (
埋め込み文字としての } には通常通り が必要にな り
ます。) 例:
$foo = q!I said, "You said, 'She said it.'"!;
$bar = q('This is it.');
$today = qx{ date };
$_ .= qq
*** The previous line contains the naughty word "$&".\n
if /(ibm|apple|awk)/; # :-)
rand(EXPR)
rand EXPR
rand ランダムな 0 から EXPR までの小数点数を返します。
(EXPR は正でなければなりません。) EXPR が省略さ れ
ると、0 から 1 の範囲の値が返されます。 srand() を
参照して下さい。
read(FILEHANDLE,SCALAR,LENGTH,OFFSET)
read(FILEHANDLE,SCALAR,LENGTH)
指定された FILEHANDLE から、LENGTH バイトのデー タ
を読み込み、変数 SCALAR に格納します。実際に読み込
めたバイト数を返し、エラーの場合は undef を返し ま
す。 SCALAR は実際に読み込まれた長さに合わせて、伸
縮します。読んだデータを文字列の始めでなく、他の場
所 に格納するために、OFFSET を指定することもできま
す。これは、実際には stdio の fread コールで実装さ
れ て い ま す。本当の read システムコールを使うに
は、sysread を参照して下さい。
readdir(DIRHANDLE)
readdir DIRHANDLE
opendir() にオープンされたディレクトリ内の、 次 の
ディレクトリエントリを返します。配列のコンテキスト
の中で使うと、残りすべてのディレクトリエントリを返
します。エントリが残っていない場合、スカラのコンテ
キストでは undefined が、配列のコンテキストでは ヌ
ルリストを返します。
readlink(EXPR)
readlink EXPR
シンボリックリンクが実装されていれば、シンボリック
リンクの値を返します。実装されていなければ、致命的
エ ラ ー を 返します。システムエラーが起こったとき
は、undefined 値を返し、$! (errno) をセッ ト し ま
す。 EXPR を省略すると、$_ を使います。
recv(SOCKET,SCALAR,LEN,FLAGS)
ソ ケッ ト か らメッセージを受け取ります。指定した
SOCKET ファイルハンドルから、LENGTH バイトのデータ
を受け取り、変数 SCALAR に格納します。 sender のア
ドレスを返し、エラーの場合は undefined 値を返し ま
す。 SCALAR は、実際に読み込まれた長さに合わせて、
伸縮します。同名のシステムコールと同じフラグを用い
ます。
redo LABEL
redo redo コマンドは、条件を再評価することなしに、ルー
プブロックのコマンドを再開します。 continue ブロッ
ク が あっ ても実行されません。 LABEL が省略される
と、最も内側のループを参照します。通常このコマンド
は、入力された内容について、自分自身をだますような
プログラムで使われます:
# 単純化した Pascal のコメント除去
# (警告: 文字列中には { や } はないものと仮定しています)
line: while (<STDIN>) {
while (s|({.*}.*){.*}|$1 |) {}
s|{.*}| |;
if (s|{.*| |) {
$front = $_;
while (<STDIN>) {
if (/}/) { # コメント終了?
s|^|$front{|;
redo line;
}
}
}
print;
}
rename(OLDNAME,NEWNAME)
ファイル名を変更します。成功すると 1 を、失敗す る
と 0 を返します。ファイルシステムの境界を越えては
働きません。
require(EXPR)
require EXPR
require EXPR か EXPR が与えられなければ $_ で指定され た、
ライブラリファイルをインクルードします。以下のよう
なサブルーチンと同じ意味になります:
sub require {
local($filename) = @_;
return 1 if $INC{$filename};
local($realfilename,$result);
ITER: {
foreach $prefix (@INC) {
$realfilename = "$prefix/$filename";
if (-f $realfilename) {
$result = do $realfilename;
last ITER;
}
}
die "Can't find $filename in \@INC";
}
die $@ if $@;
die "$filename did not return true value" unless $result;
$INC{$filename} = $realfilename;
$result;
}
同じ名前で指定されたファイルは、二度はインクルード
されないことに注意して下さい。どの初期化コードの起
動も成功したこと示すため、ファイルの最後の文で、真
を返さなければなりません。だから、慣習的にそういう
ファイルは、必ず真を返すということが確かでな け れ
ば、"1;" で終るようにします。
reset(EXPR)
reset EXPR
reset 一般にループの終りで変数をクリアするのに continue
ブロックの中で使われ、再びそれが働くように ?? 検索
を リセットします。式は 1 文字ずつ分けてリストした
もの (ハイフンで範囲指定) として解釈されます。それ
らの文字の一つで始まる変数や配列はみな初期状態にリ
セットされます。式を省略すると、一度だけマッチする
検 索 (?pattern?) をリセットし、再びマッチするよう
にします。現パッケージ内の変数と検索のみをリセット
します。常に 1 を返します。例:
reset 'X'; # すべての X 変数をリセットします
reset 'a-z'; # 小文字の変数すべてをリセットします。
reset; # ?? 検索をリセットします。
注 意: ARGV や ENV を消してしまうため、"A-Z" をリ
セットするのは勧められません。
dbm 連想配列に reset を使っても、dbm ファイルを 変
更 しません。 (しかし、perl がキャッシュしたエント
リは皆フラッシュするので、 dbm ファイルを共有し て
い る 場 合 は、便利です。便利でないかもしれません
が。)
return LIST
指定した値で、サブルーチンから返ります。 (サブルー
チンは、自動的に最後に評価された式の値を返すことに
注意して下さい。これは、好まれる方法です--明示的な
return の使用で、やや遅くなります。)
reverse(LIST)
reverse LIST
配 列のコンテキストでは、LIST の要素を逆順に並べた
配列を返します。スカラのコンテキストでは、LIST の
最初の要素のバイト列を逆順にした文字列を返します。
rewinddir(DIRHANDLE)
rewinddir DIRHANDLE
DIRHANDLE に関し、readdir() で読み始める現在 位 置
を、ディレクトリの先頭にセットします。
rindex(STR,SUBSTR,POSITION)
rindex(STR,SUBSTR)
STR 内 で、SUBSTR が 最 後に現れる位置を返す他
は、index と全く同じに動作します。 POSITION が指定
さ れ ると、その位置の前で最後に現れた位置を返しま
す。
rmdir(FILENAME)
rmdir FILENAME
FILENAME で指定されたディレクトリが空なら消去し ま
す。 成 功 す る と 1 を、失敗すると 0 を返し、$!
(errno) をセットします。 FILENAME が省 略 さ れ る
と、$_ を使います。
s/PATTERN/REPLACEMENT/gieo
パターンに合う文字列を検索し、見つかると置換テキス
トに置き換えて、置換が行なわれた数を返します。でな
ければ、偽 (0) を返します。 "g" はオプションです。
もしあれば、マッチしたパターンはすべて置換されるこ
と を 意 味します。 "i" もオプションです。もしあれ
ば、マッチングは大文字小文字の区別なく行なわれるこ
と を 意 味します。 "e" もオプションです。もしあれ
ば、置換文字列はダブルクォートで囲まれた文字列のよ
うにというより、式として評価されなければならないこ
とを意味します。英数字でない文字ならなんでも、/ に
置き換えて区切り文字にできます。シングルクォートが
使われると、置換文字列の中で変数の挿入が行なわれま
せ ん (e 修飾子はこれに優先します)。バッククォート
` が使われると、置換文字列はコマンドとして実 行 さ
れ、その出力が実際の置換テキストとして使われること
になります。 PATTERN が <>, () で 区 切 ら れ る
と、REPLACEMENT は、それ自身のクォートを持ち、それ
は <>, () であっても、そうでなくても良いことになり
ま す。 例 えば、s(foo)(bar) や s<foo>/bar/ のよう
に。 =~ や !~ 演算子を介する文字列指定がされなかっ
たときは、$_ 文字列が検索、置換されます。 (=~ で指
定された文字列は、スカラ変数、配列の要素、それらへ
の代入等でなくてはなりません。すなわち左辺値という
ことです。) パターンが、文字列の終りをテストする $
で なく、変数に見える $ を含む場合は、その変数が実
行時にパターンに挿入されます。初回だけ変数が挿入さ
れてコンパイルされるパターンを使いたいなら、終りに
"o" を付けて下さい。 PATTERN がヌル文字列に評価 さ
れたときは、代わりに最後に成功した正規表現が使われ
ます。正規表現のセクションを参照して下さい。例:
s/\bgreen\b/mauve/g; # wintergreen を変更しません
$path =~ s|/usr/bin|/usr/local/bin|;
s/Login: $foo/Login: $bar/; # 実行時パターン
($foo = $bar) =~ s/bar/foo/;
$_ = 'abc123xyz';
s/\d+/$&*2/e; # 'abc246xyz' になる
s/\d+/sprintf("%5d",$&)/e; # 'abc 246xyz' になる
s/\w/$& x 2/eg; # 'aabbcc 224466xxyyzz' になる
s/([^ ]*) *([^ ]*)/$2 $1/; # 始めの2フィールドを交換
(最後の例では \ の代わりに $ を使っていることに 注
意。正規表現のセクションを参照して下さい。)
scalar(EXPR)
EXPR を 強 制 的にスカラのコンテキストで解釈させ
て、EXPR の値を返します。
seek(FILEHANDLE,POSITION,WHENCE)
FILEHANDLE のポインタを、丁度 stdio の fseek() の
ように任意の位置にします。 FILEHANDLE は、ファイル
ハンドルの名前を与える式でもかまいません。成功する
と 1 を、失敗すると 0 を返します。
seekdir(DIRHANDLE,POS)
DIRHANDLE について readdir() の読む現在位置をセッ
トします。 POS は、telldir() の返す値でなければ な
り ま せ ん。 相当するシステムライブラリルーチン同
様、directory compaction については同じ注意が必 要
です。
select(FILEHANDLE)
select 現 在 select されたファイルハンドルを返します。
FILEHANDLE を与えられると、出力用の現在のデフォ ル
トファイルハンドルをセットします。これには二つの効
果があります。一つは、ファイルハンドルの無い write
や print が、デフォルトでこの FILEHANDLE に行なわ
れるということです。二つ目は、出力に関連する変数参
照が、この出力チャネルを参照するということです。例
えば、form フォーマットの先頭を、一つ以上 の 出 力
チャネルにセットしなければならないとき、次のように
すると良いでしょう:
select(REPORT1);
$^ = 'report1_top';
select(REPORT2);
$^ = 'report2_top';
FILEHANDLE は、実際のファイルハンドルの名前を与 え
る式でもかまいません。このように:
$oldfh = select(STDERR); $| = 1; select($oldfh);
select(RBITS,WBITS,EBITS,TIMEOUT)
これは、ビットマスクを指定して select システムコー
ルを呼び出しします。ビットマスクは、以下のよ う に
fileno() や vec() を使って作成されます。
$rin = $win = $ein = '';
vec($rin,fileno(STDIN),1) = 1;
vec($win,fileno(STDOUT),1) = 1;
$ein = $rin | $win;
たくさんのファイルハンドルを select したいときは、
サブルーチンを書いた方が良いかもしれません。
sub fhbits {
local(@fhlist) = split(' ',$_[0]);
local($bits);
for (@fhlist) {
vec($bits,fileno($_),1) = 1;
}
$bits;
}
$rin = &fhbits('STDIN TTY SOCK');
通常の使い方は、
($nfound,$timeleft) =
select($rout=$rin, $wout=$win, $eout=$ein, $timeout);
また、何かが ready となるまでブロックしておくには、こうなります。
$nfound = select($rout=$rin, $wout=$win,
$eout=$ein, undef);
ビットマスクはどれも undef にもできます。 TIMEOUT
は秒で指定され、小数点数でもかまいません。注意: す
べての実装で $timeleft を返せるわけではあ り ま せ
ん。できない場合、常に与えられた $timeout に等しい
値の $timeleft を返します。
semctl(ID,SEMNUM,CMD,ARG)
System V IPC 関数の semctl を呼び出します。 CMD が
&IPC_STAT か &GETALL な ら、ARG は返って来た
semid_ds 構造体か、セマフォ値配列を保持する変数 で
な け れ ば な りません。 ioctl 同様、エラーの場合
undefined 値が、0 の場合 "0 but true" が、それ以外
の場合実際の戻り値が返されます。
semget(KEY,NSEMS,SIZE,FLAGS)
System V IPC 関数 semget を呼び出します。セマフォ
id を返し、エラーの場合は undefined 値を返します。
semop(KEY,OPSTRING)
シ グ ナ ル や wait のようなセマフォ操作を実行する
System V IPC 関数 semop を呼び出します。 OPSTRING
は、semop 構造体に pack された配列でなければなりま
せん。各 semop 構 造 体 は 'pack("sss", $semnum,
$semop, $semflag)' で生成できます。セマフォ操作の
数は、OPSTRING の長さによります。成功すると真 を、
エラーでは偽を返します。例として、以下のコードでは
セマフォ id $semid のセマフォ $semnum を待ちます。
$semop = pack("sss", $semnum, -1, 0);
die "Semaphore trouble: $!\n" unless semop($semid, $semop);
セ マ フォにシグナルを送るには、"-1" を "1" にしま
す。
send(SOCKET,MSG,FLAGS,TO)
send(SOCKET,MSG,FLAGS)
ソケットにメッセージを送ります。同名のシステムコー
ルと同じフラグを用います。接続されていないソケット
では、送り先を TO として指定しなければなりません。
送っ た 文字数を返します。エラーの場合は undefined
値を返します。
setpgrp(PID,PGRP)
指定した PID のカレントプロセスグループをセット し
ます。 PID は、カレントプロセスでは 0 です。 setp-
grp(2) が実装されていないマシンでは、致命的エラ ー
となります。
setpriority(WHICH,WHO,PRIORITY)
プロセス、プロセスグループ、ユーザのカレントプライ
オリティをセットします。 (setpriority(2) を参照 し
て 下さい。) setpriority(2) が実装されていないマシ
ンでは、致命的エラーになります。
setsockopt(SOCKET,LEVEL,OPTNAME,OPTVAL)
リクエストされたソケットオプションをセットします。
エ ラーでは undefined を返します。引数を渡したいの
で無ければ、OPTVAL は undef 値を指定してもかまいま
せん。
shift(ARRAY)
shift ARRAY
shift 配 列の最初の要素を配列から除き、その要素を返しま
す。配列は 1 だけ短くなり、他のすべての要素はず れ
ます。配列に要素がないときは、undefined 値を返しま
す。 ARRAY を省略すると、メインプロ グ ラ ム で は
@ARGV 配列を shift し、サブルーチンでは @_ 配列を
shift します。 (これは、辞書的に決められていま す)
unshift(), push(), pop() を 参 照 して下さい。
shift() と unshift() は、push() と pop() が配列 の
右 端 に行なうのと同じことを、配列の左端で行ないま
す。
shmctl(ID,CMD,ARG)
System V IPC 関数 shmctl を呼び出します。 CMD が
&IPC_STAT のとき、 ARG は、返された shmid_ds 構造
体を保持する変数でなくてはなりません。 ioctl 同 様
の 戻 り値を返します。エラーでは undefined 値を、0
では "0 but true" を、それ以外では実際の値を返しま
す。
shmget(KEY,SIZE,FLAGS)
System V IPC 関数 shmget を呼び出します。共有メモ
リのセグメント id を返します。エラ ー で は、unde
fined 値を返します。
shmread(ID,VAR,POS,SIZE)
shmwrite(ID,STRING,POS,SIZE)
Syste V の共有メモリセグメント ID を、位置 POS か
ら始まるサイズ SIZE にて attach し、copy in/out
し、detach することで、読み込みと書き込みを行ない
ます。読み込み時、VAR は読まれたデータを保持する変
数 でなければなりません。書き込み時に、STRING が長
過ぎると、SIZE バイトだけが使われます。STRING が短
過 ぎると、SIZE バイトを埋めるのにヌルが書き込まれ
ます。成功すると真を、エラーでは偽を返します。
shutdown(SOCKET,HOW)
ソケット接続を HOW で指示された流儀に従って シャッ
ト ダ ウンします。同名のシステムコールと同様に HOW
を解釈します。
sin(EXPR)
sin EXPR
EXPR (ラジアンで表現) のサインを返します。 EXPR を
省略すると $_ のサインを取ります。
sleep(EXPR)
sleep EXPR
sleep EXPR 秒間スクリプトを止めます。 EXPR がなければ永
久に止めます。プロセスに SIGALRM を送ることで、 割
り 込 ま れます。実際に sleep した秒数を返します。
sleep() は、しばしば alarm() を使って実装されて い
る ので、おそらく alarm() と sleep() は 混在させる
ことはできないでしょう。
socket(SOCKET,DOMAIN,TYPE,PROTOCOL)
指定された種類のソケットをオープンして、ファイルハ
ン ドル SOCKET に結びつけます。 DOMAIN, TYPE, PRO
TOCOL は、同名のシステムコールと同様に指定します。
perl ライブラリファイルから簡単に適当な値を得るに
は、h2ph を sys/soket.h に対して実行する必要がある
かもしれません。成功すると真を返します。プロセス間
通信のセクションの例を参照して下さい。
socketpair(SOCKET1,SOCKET2,DOMAIN,TYPE,PROTOCOL)
指定されたドメインの指定された型で、無名のソケット
ペアを生成します。 DOMAIN, TYPE, PROTOCOL は、同名
のシステムコールと同じように指定します。実装されて
いない場合は、致命的エラーとなります。成功すると真
を返します。
sort(SUBROUTINE LIST)
sort(LIST)
sort SUBROUTINE LIST
sort BLOCK LIST
sort LIST
LIST をソートし、ソート済みの配列値を返します。 存
在しない配列値は、削られます。 SUBROUTINE や BLOCK
が省略されると、標準的な文字の比較による順でソート
します。 0 より小さい整数、0、0 より大きい整数を返
すような SUBROUTINE の名前を指定すると、配列の要素
の 並べ方に従って順に並べ直します。 (<=> と cmp 演
算子は、このようなルーチンでは非常に便利です) SUB
ROUTINE は、スカラ変数名でもかまいません。その値と
して使用するサブルーチンの名前が入っていれば良いの
です。 SUBROUTINE 名の代わりに、BLOCK を指定して、
無名のインラインソートサブルーチンとして用いること
もできます。
効率を良くするため、通常のサブルーチン呼び出しコー
ドをバイパスしています。そのため、次のような影響が
あります。サブルーチンは再帰的であってはならず、比
較される 2 要素は @_ を介してではなく、$a と $b を
介してサブルーチンに渡されます。 (以下の例を参照し
て下さい。) これらは参照渡しなので、$a や $b を 変
更してはいけません。
例:
# 辞書順のソート
@articles = sort @files;
# 同じものだが、明示的なソートルーチン
@articles = sort {$a cmp $b} @files;
# 同じものだが逆順
@articles = sort {$b cmp $a} @files;
# 数値的に昇順でソート
@articles = sort {$a <=> $b} @files;
# 数値的に降順でソート
@articles = sort {$b <=> $a} @files;
# 明示的にサブルーチン名を使ったソート
sub byage {
$age{$a} <=> $age{$b}; # 整数と仮定
}
@sortedclass = sort byage @class;
sub reverse { $b cmp $a; }
@harry = ('dog','cat','x','Cain','Abel');
@george = ('gone','chased','yz','Punished','Axed');
print sort @harry;
# AbelCaincatdogx と出力
print sort reverse @harry;
# xdogcatCainAbel と出力
print sort @george, 'to', @harry;
# AbelAxedCainPunishedcatchaseddoggonetoxyz と出力
splice(ARRAY,OFFSET,LENGTH,LIST)
splice(ARRAY,OFFSET,LENGTH)
splice(ARRAY,OFFSET)
配 列 か ら OFFSET と LENGTH で指定された要素を除
き、LIST の要素と入れ替えます。配列から除かれた 要
素 を 返 し ます。配列は必要に応じて伸縮されます。
LENGTH を省略すると、OFFSET から先はすべて除かれま
す。以下は皆同等となります。 ($[ == 0 であると仮定
した場合)
push(@a,$x,$y) splice(@a,$#a+1,0,$x,$y)
pop(@a) splice(@a,-1)
shift(@a) splice(@a,0,1)
unshift(@a,$x,$y) splice(@a,0,0,$x,$y)
$a[$x] = $y splice(@a,$x,1,$y);
次の例では、配列長は配列の前に渡されると仮定しています:
sub aeq { # compare two array values
local(@a) = splice(@_,0,shift);
local(@b) = splice(@_,0,shift);
return 0 unless @a == @b; # 同じ長さ?
while (@a) {
return 0 if pop(@a) ne pop(@b);
}
return 1;
}
if (&aeq($len,@foo[1..$len],0+@bar,@bar)) { ... }
split(/PATTERN/,EXPR,LIMIT)
split(/PATTERN/,EXPR)
split(/PATTERN/)
split 文字列を文字列の配列に分けて、その配列を返します。
( 配列のコンテキストではない場合、見つかったフィー
ルドの数を返し、 split したものは @_ 配列に入れ ま
す。 (配列のコンテキストでは、パターン区切りとして
?? を使うことで強制的に @_ に split させられ ま す
が、 そ れでも配列値を返します。)) EXPR を省略する
と、$_ 文字列を split します。 PATTERN も省略す る
と、 空 白文字 (/[ \t\n]+/) で split します。 PAT
TERN にマッチするものは何でもフィールドを分ける 区
切 りと解釈されます。 (区切りは 1 文字より長くても
よいことに注意して下さい。) LIMIT が指定されると、
そ れを越えない数に split されます (少ない場合もあ
ります)。 LIMIT が指定されないと、後に続くヌルフィ
ー ルドは除かれます (pop()を使う人は良く覚えておい
た方がよいでしょう)。ヌル文字にマッチするパター ン
( ヌルパターン // と混同しないで下さい。 // はヌル
文字にマッチするパターンの一つにすぎません。) は、
マッ チ するすべての点で EXPR を一文字ずつに split
します。例えば:
print join(':', split(/ */, 'hi there'));
は、'h:i:t:h:e:r:e' を出力します。
LIMIT パラメータは、行を部分的に split すること に
使われます。
($login, $passwd, $remainder) = split(/:/, $_, 3);
( リ ス トに代入するとき、LIMIT が省略されていると
perl は不必要な動作を避けるためにリストの変数の 数
よ り一つ大きい LIMIT を与えます。上記のリストでは
LIMIT はデフォルトで 4 だったはずです。時間に制 限
の あ るアプリケーションでは、本当に必要な数以上の
フィールドには split しないようにすべきです。)
PATTERN が括弧を含むときは、区切りとしてマッチする
文字列により、更に配列要素が作成されます。
split(/([,-])/,"1-10,20");
は以下の配列値を作ります。
(1,'-',10,',',20)
パ ターン /PATTERN/ は、実行時に変わるパターンを指
定する式で置き換え可能です。 (実行時コンパイルを一
回 にしたければ、/$variable/o を使って下さい。) 特
別なケースとして空白 (' ') を指定すると、引数無 し
で split する場合と同様ですが、先頭に空白があって
もヌルフィールドは作られません。つまり split(' ')
は、 awk のデフォルトの動作をエミュレートすること
ができるわけで、split(/ /) は先頭に空白がある と、
最初にその数だけヌルフィールドを作ります。
例:
open(passwd, '/etc/passwd');
while (<passwd>) {
($login, $passwd, $uid, $gid, $gcos, $home, $shell)
= split(/:/);
...
}
( 上の例の $shell は改行文字を含みます。 chop() を
参照して下さい。) join を参照して下さい。
sprintf(FORMAT,LIST)
通常の printf 変換でフォーマットされる文字列を返し
ます。 * 文字はサポートされていません。
sqrt(EXPR)
sqrt EXPR
EXPR の平方根を返します。 EXPR を省略すると、$_ の
平方根を返します。
srand(EXPR)
srand EXPR
rand 演算子のために、乱数用の seed をセッ ト し ま
す。 EXPR を省略すると、srand(time) を実行します。
stat(FILEHANDLE)
stat FILEHANDLE
stat(EXPR)
stat SCALARVARIABLE
EXPR という名前のファイルや FILEHANDLE でオープ ン
さ れ たファイルの情報を示す 13 要素の配列を返しま
す。 stat が失敗するとヌルリストを返します。普通次
のように使います:
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
$atime,$mtime,$ctime,$blksize,$blocks)
= stat($filename);
stat に特殊ファイルハンドル _ を渡すと、stat は実
行されず最後に行なわれた stat やファイルテストで使
われた stat 構造体の内容を返します。例:
if (-x $file && (($d) = stat(_)) && $d < 0) {
print "$file is executable NFS file\n";
}
( この例は、NFS 下でデバイス番号が負になるマシンで
のみ動作します。)
study(SCALAR)
study SCALAR
study SCALAR (指定しなければ $_) について、それが次に 変
更される前に多くのパターンマッチを予想してあらかじ
め行います。検索をするパターンの性質や数、検索され
る文字列中の文字の出現頻度分布によっては、時間を節
約できるかもしれませんし、できないかもしれません。
--多分これを使った場合と使わない場合で、実行時どち
らが速いかを比べてみたいでしょう。たくさんの短い定
数文字列(より複雑なパターンの定数部を含む)をスキャ
ンするループで最も恩恵にあずかれるでしょう。一度に
一 つの study しか効果がありません。--別のスカラを
study すると、先に study したものは "unstudied" と
なってしまいます。 (study の動作の仕方は次の通りで
す: 検索される文字列のすべての文字のリンクリストを
作 ります。そうすると例えば、どこに 'k' の文字があ
るかがすべてわかるわけです。いくつかの C のプロ グ
ラムと英文から作成された統計頻度表に基づき、各検索
文字について、最も頻度が少ない文字を選びます。この
"頻度が少ない" 文字を調べるのです。)
次 の 例は、あるパターンを含むすべての行の前にイン
デックスを含むエントリを挿入します:
while (<>) {
study;
print ".IX foo\n" if /\bfoo\b/;
print ".IX bar\n" if /\bbar\b/;
print ".IX blurfl\n" if /\bblurfl\b/;
...
print;
}
/\bfoo\b/ を検索するとき、'f' は 'o' よりも頻度 が
少ないため、$_ の中で 'f' を含む位置が探されます。
一般に、病的な場合を除いて、これは非常にうまくいき
ます。唯一、最初の時点でリンクリストを作成するため
にかかる以上の時間を節約できるかが問題になります。
実行するまで解らない文字列を検索しなければならない
場合、全ループを一つの文字列として解析し eval する
ことで、すべてのパターンを毎回再コンパイルするのを
避けることができることを覚えておきましょう。それに
加 え て 全ファイルが 1 レコードになるように $/ を
undef すると、大変速くなり、fgrep のように特殊化し
た プ ログラムより速くなることも多いです。以下の例
は、ファイルのリスト (@files) と 単 語 の リ ス ト
(@words) を検索し、マッチするファイル名を出力しま
す:
$search = 'while (<>) { study;';
foreach $word (@words) {
$search .= "++\$seen{\$ARGV} if /\\b$word\\b/;\n";
}
$search .= "}";
@ARGV = @files;
undef $/;
eval $search; # これは(メモリ不足で)泣きそう
$/ = "\n"; # 普通の入力区切りに戻そう
foreach $file (sort keys(%seen)) {
print $file, "\n";
}
substr(EXPR,OFFSET,LEN)
substr(EXPR,OFFSET)
EXPR から部分文字列を取り出し、それを返します。 $[
を セッ ト しない限り、最初の文字はオフセット 0 で
す。 OFFSET が負だと、文字列の終りから OFFSET だけ
離 れた位置から始めます。 LEN を省略すると、終端ま
でのすべての文字列を返します。 substr() 関数は左辺
値としても使えます。その場合 EXPR は左辺値でなくて
はなりません。 LEN より短いものを代入すると、文 字
列は短くなり、長いものを代入するとそれを含められる
ように長くなります。文字列を同じ長さに保つた め に
は、sprintf() を使ってパディングまたは切り捨てをし
なければならないかもしれません。
symlink(OLDFILE,NEWFILE)
OLDFILE へのシンボリックリンク NEWFILE を作成し ま
す。成功すると 1 を、失敗すると 0 を返します。シン
ボリックリンクをサポートしないシステムでは、実行時
に 致 命 的 エラーとなります。これをチェックするに
は、eval を使います:
$symlink_exists = (eval 'symlink("","");', $@ eq '');
syscall(LIST)
syscall LIST
リストの最初の要素で指定されたものに、残りの要素を
引数として付けて、システムコールを呼び出します。実
装されていないと致命的エラーとなります。引数は次の
ように解釈されます: 与えられた引数が数字なら、引数
は整数として渡されます。そうでなければ、文字列への
ポインタが渡されます。結果が受け取れるように、書き
込まれるべき文字列を十分長くしておくのは、あなたの
責任です。数字の引数がリテラルでなく、それまで数字
のコンテキストで解釈されていなかったものなら、強制
的 に数字に見せるように、 0 を足す必要があるかもし
れません。
# h2ph を実行しておく必要があるかもしれません
require 'syscall.ph';
syscall(&SYS_write, fileno(STDOUT), "hi there\n", 9);
sysread(FILEHANDLE,SCALAR,LENGTH,OFFSET)
sysread(FILEHANDLE,SCALAR,LENGTH)
システムコール read(2) を使って、指定した FILEHAN
DLE か ら LENGTH バイトのデータを読み込み、変数
SCALAR に格納します。これは標準入出力を経由しな い
の で、read と混在して使うと、混乱するかもしれませ
ん。実際に読み込まれたバイト数を返します。エラーの
場 合は undef を返します。 SCALAR は実際に読み込ま
れた長さによって伸縮します。文字列の始めでなく途中
にデータを格納するように、OFFSET を指定できます。
system(LIST)
system LIST
"exec LIST" と全く同じことを行ないますが、違いは最
初に fork が実行されて、親プロセスは子プロセスが終
了 す るのを待つことです。引数の処理は、引数の数に
よって変わることに注意して下さい。戻り値は、wait()
で返るプログラムの終了時ステータスになります。実際
の終了時ステータスを得るには、256 で割って下さい。
exec を参照。
syswrite(FILEHANDLE,SCALAR,LENGTH,OFFSET)
syswrite(FILEHANDLE,SCALAR,LENGTH)
シ ス テムコール write(2) を使って、指定した FILE
HANDLE に変数 SCALAR から LENGTH バイトのデータ を
書 き 込 み ま す。 これは標準入出力を経由しないの
で、print と混在して使うと、混乱するかもしれ ま せ
ん。実際に書き込まれたバイト数を返します。エラーの
場合は undef を返します。 OFFSET で、文字列の始 め
でなく途中からデータを読むように指定できます。
tell(FILEHANDLE)
tell FILEHANDLE
tell FILEHANDLE の現在のファイル位置を返します。 FILE
HANDLE は、実際のファイルハンドルの名前を与える 式
でもかまいません。 FILEHANDLE を省略すると、最後に
読んだファイルを使います。
telldir(DIRHANDLE)
telldir DIRHANDLE
DIRHANDLE について readdir() ルーチンの現在の位 置
を返します。この値は、ディレクトリの特定の位置をア
クセスするために、seekdir() の引数に使います。相当
するシステムライブラリルーチン同様、directory com
paction については同じ注意が必要です。
time 1970 年 1 月 1 日 00:00:00 (UTC) からの通算の秒数(
閏秒無し)を返します。 gmtime() や localtime() に使
うことができます。
times 現在のプロセスと子プロセスのユーザ、システム時 間(
秒)からなる 4 要素の配列を返します。
($user,$system,$cuser,$csystem) = times;
tr/SEARCHLIST/REPLACEMENTLIST/cds
y/SEARCHLIST/REPLACEMENTLIST/cds
SEARCHLIST にある文字が出現したら、すべて REPLACE
MENTLIST の相当する文字に変換します。変換または 削
除された文字の数を返します。 =~ や !~ 演算子を介し
た文字列の指定をしなかった場合、$_ 文字列が変換 さ
れ ます。 (=~ で指定した文字列は、スカラ変数か配列
の要素かそれらへの代入でなければいけません。 つ ま
り、 左 辺値ということになります。) sed 信者のため
に、 tr の別名 y が用意されていま す。 SEARCHLIST
が [], <>, () で区切られていると、REPLACEMENTLIST
は、それ自身のクォートを持ち、それは [], <>, () で
あっ て も、そうでなくても良いことになります。例え
ば、 tr[A-Z][a-z] または tr(+-*/)/ABCD/ のようにな
ります。
c 修飾子が指定されると、SEARCHLIST の文字セットは
補間されます。 d 修飾子が指定される と、SEARCHLIST
で 指定された文字で REPLACEMENTLIST に対応するもの
がないものは皆、削除されます。 (これは、SEARCHLIST
で見つかったものを何でも削除してしまうような tr プ
ログラムの挙動よりも、やや柔軟です。) s 修飾子が指
定されると、変換されて同じ文字が続いたとき、それを
1 文字に縮めます。
d 修飾子が使われると、REPLACEMENTLIST は常に指定さ
れた通りに解釈されます。それ以外の場合で、REPLACE
MENTLIST が SEARCHLIST より短いときは、同じ長さ に
な る ま で 最 後の文字が繰り返されます。 REPLACE
MENTLIST がヌルだと、SEARCHLIST がコピーされます。
これは、あるクラスに含まれる文字をカウントしたり、
あるクラスの文字の重複を縮めるときに便利です。
例:
$ARGV[1] =~ y/A-Z/a-z/; # 小文字に統一します
$cnt = tr/*/*/; # $_ の中の * を数えます
$cnt = tr/0-9//; # $_ の中の数字を数えます
tr/a-zA-Z//s; # bookkeeper -> bokeper
($HOST = $host) =~ tr/a-z/A-Z/;
y/a-zA-Z/ /cs; # アルファベット以外を 1 文字の空白にします
tr/\200-\377/\0-\177/; # 8 ビット目を消します
truncate(FILEHANDLE,LENGTH)
truncate(EXPR,LENGTH)
FILEHANDLE や EXPR の名前のファイルを指定した長 さ
に切り詰めます。システムに truncate が実装されてい
ないと、致命的エラーになります。
umask(EXPR)
umask EXPR
umask プロセスに umask をセットし、変更前の値を 返 し ま
す。 EXPR が省略されると、単に現在の umask を返し
ます。
undef(EXPR)
undef EXPR
undef EXPR の値を undefined とします。これは左辺値でなけ
ればなりません。スカラ値、配列全体、サブルーチン名
(& を使う) の場合でのみ使えます。 (undef は、多 分
ほとんどの予約変数、dbm 配列値では期待する動作とな
りません。) undef は、常に undefined 値を 返 し ま
す。 EXPR を省略することもできます。その場合は何も
undef されませんが、それでも undefined 値を得る こ
とができます。例えば、サブルーチンから return する
ときです。例:
undef $foo;
undef $bar{'blurfl'};
undef @ary;
undef %assoc;
undef &mysub;
return (wantarray ? () : undef) if $they_blew_it;
unlink(LIST)
unlink LIST
リストに含まれるファイルを削除します。削除に成功し
たファイルの数を返します。
$cnt = unlink 'a', 'b', 'c';
unlink @goners;
unlink <*.bak>;
注 意: unlink は、自分がスーパユーザで perl に -U
フラグを付けている場合を除くとディレクトリを消去は
しません。これらの条件がそろったとしても、ディレク
トリの unlink はシステムにダメージを与えることがあ
る ので、気をつけて下さい。代わりに rmdir を使って
下さい。
unpack(TEMPLATE,EXPR)
unpack は pack の逆を行ないます: 構造体を示す文 字
列を引数に取り、それを配列値に出力し、配列値を返し
ます。 (スカラのコンテキストでは、生成された最初の
値のみを返します。) TEMPLATE は、pack 関数と全く同
じフォーマットになります。以下は、substr を実行 す
るサブルーチンです:
sub substr {
local($what,$where,$howmuch) = @_;
unpack("x$where a$howmuch", $what);
}
そして、
sub ord { unpack("c",$_[0]); }
というのもあります。更に、フィールドの前に %<数字>
の添字を付けることにより、項目そのものの代わりに、
項目の<数字>ビットのチェックサムが欲しいという指定
になります。デフォルトは、16 ビットのチェックサ ム
です。次の例で、System V の sum プログラムと同じ数
が計算されます:
while (<>) {
$checksum += unpack("%16C*", $_);
}
$checksum %= 65536;
unshift(ARRAY,LIST)
視点によって、 shift の逆、または push の逆を行 な
います。 LIST を配列の前に付け加え、新しい配列の要
素の数を返します。
unshift(ARGV, '-e') unless $ARGV[0] =~ /^-/;
utime(LIST)
utime LIST
リストの各ファイルのアクセス時刻と最終変更時刻を変
えます。リストの最初の二つの要素には、*数値*で表さ
れたアクセス時刻と変更時刻がこの順で入っていなけれ
ば な りません。変更に成功したファイルの数が返りま
す。各ファイルの inode 変更時刻には現在時間が セッ
トされます。以下は、"touch" コマンドの例です:
#!/usr/bin/perl
$now = time;
utime $now, $now, @ARGV;
values(ASSOC_ARRAY)
values ASSOC_ARRAY
名前付き連想配列のすべての値からなる普通の配列を返
します。値は、見かけ上ランダムな順で返るように見え
ま す が、 同 じ 連想配列に対して、 keys() 関数 や
each() 関数が生成するものと同じ順 に な り ま す。
keys() と each() を参照して下さい。
vec(EXPR,OFFSET,BITS)
文字列を unsigned integer のベクトルとして扱い、指
定したビットフィールドの値を返します。代入もできま
す。 BITSは、2 の累乗で 1 から 32 まででなければな
りません。
vec() に生成されたベクトルは、論理演算子 |, &, ^
で操作することができ、両方のオペランドが文字列のと
き、ビットベクトル演算をするものとみなされます。古
いプログラムを守るために、プログラム中に少なくとも
一つの vec() がないと、この解釈はなされません。
ビットベクトルを 0 や 1 の文字列や配列に変換するに
は、以下を使って下さい:
$bits = unpack("b*", $vector);
@bits = split(//, unpack("b*", $vector));
ビットの正確な長さがわかるならば、* の代わりに使う
ことができます。
wait 子プロセスが終了するのを待ち、死んだプロセスの pid
を 返 し ます。子プロセスがないときは、-1 を返しま
す。終了時ステータスは $? に返されます。
waitpid(PID,FLAGS)
特定の子プロセスが終了するのを待ち、死んだプロセス
の pid を返します。そのような子プロセスがなけれ
ば、-1 を返します。終了時ステータスは $? に返さ れ
ます。次のように書くと、
require "sys/wait.h";
...
waitpid(-1,&WNOHANG);
どのプロセスに対しても、non-blocking wait を実行で
きます。 non-blocking wait は、 waitpid (2) か、ま
た は wait4 (2) システムコールをサポートしているマ
シンでのみ使えます。しかし、FLAGS 0 での 特 殊 な
pid の wait はどこでも実装されています。 (perl
は、終了したものの perl スクリプトには採り入れられ
ていないプロセスのステータス値を覚えていることでシ
ステムコールをエミュレートします。)
wantarray
現在実行しているサブルーチンのコンテキストが配列値
なら真を返します。スカラのコンテキストに見えれば、
偽を返します。
return wantarray ? () : undef;
warn(LIST)
warn LIST
"die" と同じようなメッセージを標準エラー出力に出し
ますが、終了しません。
write(FILEHANDLE)
write(EXPR)
write 指 定したファイルに、関連付けられたフォーマットを
使って、フォーマットレコード (複数行も可) を書き込
みます。デフォルトで、フォーマットはファイルハンド
ルと同じ名前を持つものになりますが、$~ 変数に フォ
ーマットの名前を明示的に割り当てることで、現在の出
力チャネル ( select を参照して下さい) に対するフォ
ーマットをセットしてもかまいません。
最 上 位の form 生成は自動的に行なわれます: フォー
マットされたレコードに対して、現在のページに十分な
空きがない場合、改頁が書き込まれて、次のページに移
ります。新しいページのヘッダには、特別なページ先頭
フォーマットが使われ、その後レコードが書き込まれま
す。デフォルトでページ先頭フォーマットは、ファイル
ハンドルの名前に "_TOP" を付け加えたものになります
が、ファイルハンドルが select されているときは、$^
変数に名前を割り当てることで、好きなフォーマットを
動的にセットしてもかまいません。現在のページに残っ
て い る行数は、変数 $- に保持されていますが、0 を
セットすることがで、強制的に新しいページに移ること
ができます。
FILEHANDLE が指定されないと、現在のデフォルト出力
チャネルに出力されます。デフォルト出力は、起 動 時
STDOUT で す が、 select 演算子で変更できます。
FILEHANDLE が EXPR のとき、その式が実行時に評価 さ
れ、結果の文字列が FILEHANDLE の名前として用いられ
ます。フォーマットについての詳細は、後述の フォ ー
マットのセクションを参照して下さい。
write は read の*逆ではない*ことに注意して下さい。
優先度
perl の演算子は次のような結合規則と優先度を持っています:
なし print printf exec system sort reverse
chmod chown kill unlink utime die return
左から右 ,
右から左 = += -= *= など
右から左 ?:
なし ..
左から右 ||
左から右 &&
左から右 | ^
左から右 &
なし == != <=> eq ne cmp
なし < > <= >= lt gt le ge
なし chdir exit eval reset sleep rand umask
なし -r -w -x など
左から右 << >>
左から右 + -
左から右 * / % x
左から右 =~ !~
右から左 ! ~ 単項の-
右から左 **
なし ++ --
左から右 '('
始めの方で述べたように、リストを引数にする演 算 子 (print
他) や、任意の単項演算子 (chdir 他) のすぐ後に同じ行の次の
トークンとして左括弧がある場合、括弧の中の演算子と引数は、
丁 度 通常のファンクションコールと同様に再優先とみなされま
す。例:
chdir $foo || die; # (chdir $foo) || die
chdir($foo) || die; # (chdir $foo) || die
chdir ($foo) || die; # (chdir $foo) || die
chdir +($foo) || die; # (chdir $foo) || die
しかし、* は || よりも優先度が高いので:
chdir $foo * 20; # chdir ($foo * 20)
chdir($foo) * 20; # (chdir $foo) * 20
chdir ($foo) * 20; # (chdir $foo) * 20
chdir +($foo) * 20; # chdir ($foo * 20)
rand 10 * 20; # rand (10 * 20)
rand(10) * 20; # (rand 10) * 20
rand (10) * 20; # (rand 10) * 20
rand +(10) * 20; # rand (10 * 20)
括弧がないと、print, sort, chmod といったリストを引数に 持
つ演算子は、演算子の左側を見ているか右側を見ているかによっ
て、非常に高くも非常に低くもなります。例えば、次の例で
@ary = (1, 3, sort 4, 2);
print @ary; # 1324 を出力
sort の右側のコンマは、sort の前に評価されますが、左側のコ
ンマは、後で評価されます。言い換えると、リストを引数に取る
演算子は、それに続くすべての引数を拾う傾向にあり、前の式に
したがって単一の命令語のように振舞います。括弧に注意深くな
ければいけないことを覚えておいて下さい:
# これらを評価すると、print を実行する前に exit します。
print($foo, exit); # 明らかにやりたいこととは違います
print $foo, exit; # これもそう
# これらは、exit を評価する前に print を実行します。
(print $foo), exit; # これはやりたいことです
print($foo), exit; # これもそう
print ($foo), exit; # さらにこれも
また、これは
print ($foo & 255) + 1, "\n";
多分一目見て期待する動作とは違うことを実行するでしょう。
サブルーチン
サブルーチンは次のように宣言されます:
sub NAME BLOCK
ルーチンに渡されたすべての引数は、配列 @_ に入ります。これ
は、($_[0], $_[1], ...) です。配列 @_ はローカル配列です
が、その値は実際のスカラパラメータへの参照になります。サブ
ルーチンの戻り値は、最後の式が評価されたときの値で、配列値
にもスカラ値にもなり得ます。また、リターン文は戻り値を指定
してサブルーチンを抜けることにも使われます。ローカル変数を
作成するには、 local 演算子を参照して下さい。
サブルーチンは、 do 演算子かまたは & 演算子を使って呼ば れ
ます。
例:
sub MAX {
local($max) = pop(@_);
foreach $foo (@_) {
$max = $foo if $max < $foo;
}
$max;
}
...
$bestday = &MAX($mon,$tue,$wed,$thu,$fri);
例:
# 行を取得し、空白で始まる行は
# 続きの行として結合されます。
sub get_line {
$thisline = $lookahead;
line: while ($lookahead = <STDIN>) {
if ($lookahead =~ /^[ \t]/) {
$thisline .= $lookahead;
}
else {
last line;
}
}
$thisline;
}
$lookahead = <STDIN>; # 最初の行を取得します
while ($_ = do get_line()) {
...
}
引数に名前を付けるには、ローカルリストへの配列の代入を使います:
sub maybeset {
local($key, $value) = @_;
$foo{$key} = $value unless $foo{$key};
}
代入は値をコピーするので、これは参照呼び出しを値呼び出しに
換える効果もあります。
サブルーチンは再帰的に呼び出せます。サブルーチンが & の 型
を使って呼び出されるとき、引数リストは省略できます。省略さ
れると、サブルーチンには @_ 配列がセットされません; その代
わり、呼び出し時に @_ 配列は、サブルーチンには可視となりま
す。
do foo(1,2,3); # 三つの引数を渡します
&foo(1,2,3); # 上と同じです
do foo(); # ヌルリストを渡します
&foo(); # 上と同じです
&foo; # 引数を渡しません--より効率的
参照渡し
サブルーチンへ配列の値を渡すのではなく、その名前を渡して、
サブルーチンがローカルなコピーに対してではなくグローバルな
配列を変更できるようにしたいときがあるでしょう。 perl では
名 前 を持つすべてのオブジェクトに対して、その名前の前に *
をつけて参照できます: *foo のように。これが評価される と、
ファイルハンドル、フォーマット、サブルーチンを含む、その名
前を持つすべてのオブジェクトを表すスカラ値と な り ま す。
local() 演算子に代入されたとき、その名前がそれに代入された
* 値を参照するようになります。例:
sub doubleary {
local(*someary) = @_;
foreach $elem (@someary) {
$elem *= 2;
}
}
do doubleary(*foo);
do doubleary(*bar);
*name への代入は今のところ local() の中でしか勧められま せ
ん。 実際には *name への代入はどこででもできますが、それ以
前の *name への参照が永遠に尾を引くかもしれません。これ に
より困ったことになるかもしれませんし、ならないかもしれませ
ん。
スカラはすでに参照渡しですが、このメカニズムを用いな く て
も、 関心のある $_[nnn] への明示的な参照を行うことで、スカ
ラの引数を変更することができます。すべての要素をスカラで渡
す こ と で、 す べ ての配列の要素を変更することができます
が、push や pop、配列のサイズの変更には * メカニズムを使わ
なければなりません。どんな場合でも、* メカニズムは多分、よ
り効率が良いはずです。
*name 値は表示不能なバイナリデータを含むので、print の引数
ま たは printf や sprintf の %s 引数として使われると、表示
を綺麗にするため '*name' という値になります。
通常 LIST メカニズムはすべての配列値をマージしてしまって、
個々の配列を取り出せなくなってしまうので、配列を変更したく
ないとしても、このメカニズムは一つの LIST にたくさんの配列
を渡すのに便利です。
正規表現
パターンマッチで使われるパターンは、バージョン 8 regexp ル
ーチンで供給されているものと同じ正規表現です。 (実際、この
ル ーチンは Henry Spencer の自由に再配布可能な再実装 V8 ル
ーチンから抜き取って使われています。) それに加えて、\w は
英数字 ("_" を含む) にマッチし、 \W は非英数字にマッチしま
す。単語境界は \b に、非単語境界は \B に。空白文 字 は \s
に、非空白文字は \S に。数字は \d に、非数字は \D にマッチ
します。 \w, \s, \d はキャラクタクラスでも使 え ま す。 ま
た、\n, \r, \f, \t, \NNN は通常と同じ意味となります。キャ
ラクタクラスの中では、\b は単語境界ではなく、バックスペ ー
スを表します。選択候補は、| で区切ります。括弧構造 ( ... )
を使うと、\<数字> はその数字番目の部分文字列にマッチ し ま
す。 (パターンの外では、数字の前に \ の代わりに常に $ を用
いなければなりません。$<数字> (と $`, $&, $') の有効 範 囲
は、 閉 じ たブロックの終りか、eval 文字列か、次のパターン
マッチまでとなります。 \<数字> 記述は、ときに現在のパタ ー
ンの外に作用しますが、それに頼ってはいけません。) 括弧は好
きなだけたくさん使ってかまいません。9 個以上の部分文字列が
あ ると、変数 $10, $11, ... が対応する部分文字列を参照しま
す。後方参照の前に少なくともその数の左括弧があると、パター
ンの中では、 \10, \11 等が部分文字列を後方参照します。そう
でなければ (以前との互換性のために) \10 は \010 のバックス
ペ ー スと同じ、\11 は \011 のタブと同じというようになりま
す。 (\1 から \9 は常に後方参照です。)
$+ は、最後の括弧でマッチしたものを返します。 $& は、 マッ
チ した文字列全体を返します。 ($0 が同じものを返していまし
たが、今は違います。) $` はマッチした文字列の前の全文字 列
を 返 します。 $' はマッチした文字列の後の全文字列を返しま
す。例:
s/^([^ ]*) *([^ ]*)/$2 $1/; # 最初の二語を交換
if (/Time: (..):(..):(..)/) {
$hours = $1;
$minutes = $2;
$seconds = $3;
}
デフォルトで、^ 文字は文字列の先頭に、$ 文字は文字列の最後
( または最後の改行文字の前) にマッチすることが保障されてお
り、 perl は文字列が一行しか含んでいないという仮定の も と
で、ある最適化を行なっています。改行が埋め込まれた場合の ^
や $ の振舞いは、矛盾を生じるでしょう。しかし、^ が文字 列
内の任意の改行の後に、$ が改行の前にマッチするような、文字
列を複数行バッファとして使いたい場合があるかもしれません。
少 々のオーバヘッドを覚悟すれば、変数 $* に 1 をセットする
ことで、それができます。 $* を 0 に設定し直せば、 perl は
元の動作に戻ります。
複数行の置換を用意にするために、. 文字は改行文字にはマッチ
しません (たとえ $* が 0 であっても)。特に次の例では、改行
文字が $_ 文字列に残ります:
$_ = <STDIN>;
s/.*(some_string).*/$1/;
改行文字が要らないなら、次のどれかを試して下さい。
s/.*(some_string).*\n/$1/;
s/.*(some_string)[^\000]*/$1/;
s/.*(some_string)(.|\n)*/$1/;
chop; s/.*(some_string).*/$1/;
/(some_string)/ && ($_ = $1);
正 規表現のどの要素の後でも中括弧で囲んだ数字を {n,m} の形
で置くことができ、n で要素がマッチする最小の回数を、m で最
大 の回数を指定します。 {n} の形は、{n,n} と同等で、正確に
n 回にマッチします。 {n,} の形は、n 回以上にマッチします。
( 中括弧が他のコンテキストの中に出て来た場合は、通常の文字
として扱われます。) * 修飾子は {0,} と、+ 修飾 子 は {1,}
と、? 修飾子は {0,1} と同等となります。 n と m のサイズに
は制限がありませんが、大きい数字はより多くのメモリを消費す
るでしょう。
perl では、 \b, \w, \n のようなバックスラッシュのつくメタ
キャラクタは、すべて英数字であることに気がつかれるこ と で
しょ う。 他の正規表現言語とは違って、英数字でないバックス
ラッシュシンボルはありません。従って、\\, \(, \), \<, \>,
\{, \} というようなものは皆、メタキャラクタではなく、文字
そのものとして解釈されます。これにより、メタキャラクタに含
まれるのではないかと心配になるような文字列をパターンに使っ
て、引用することが容易になります。英数字でないすべての文字
の引用は、このようにします:
$pattern =~ s/(\W)/\\$1/g;
フォーマット
write 演算子で使う出力レコードフォーマットは、次のように宣
言します:
format NAME =
FORMLIST
.
NAME を省略すると、"STDOUT" フォーマットが定義され ま す。
FORMLIST は複数行から成り、各行は次の三つの型のいずれかと
なります:
1. コメント
2. 一つの出力行のフォーマットを示す "picture" 行
3. picture 行に値を与える引数行
picture 行は、その中で値が置換される特定のフィールドを除け
ば、 見 た 目そのままに出力されます。各 picture フィールド
は、@ か ^ で始まります。 @ フィールド (配列の先頭の @ と
混乱しないように) は通常の場合で、^ フィールドは基本的な複
数行テキストブロックを埋めるのに使われます。フィールドの長
さは、<, >, | の繰り返しで埋めることで指定し、それぞれ左寄
せ、右寄せ、センタリングを意味します。右寄せの別な形 と し
て、# 文字を (それに . を付けても良い) 数字フィールドの指
定として使うこともできます。 (@ のかわ り に ^ を 使 う
と、undefined なフィールドが空白になります。) これらのフィ
ールドに与えられた値が改行を含むと、改行までのテキストのみ
が出力されます。特殊フィールド @* は複数行の値の出力に使わ
れます。その行に書かれているのは @* だけでなくてはいけませ
ん。
値は、次の行で指定され、picture フィールドと同じ順となりま
す。値はコンマで区切られていなければなりません。
@ でなく ^ で始まる picture フィールドは、特別な扱いになり
ます。指定する値は、テキスト文字列が入っているスカラ変数名
でなければいけません。 perl は、フィールドに入れられるだけ
たくさんのテキストを入れ、変数が次に参照されるときに続きが
出力されるように、文字列の先頭からそのテキストを削ります。
通常、テキストのブロックを出力するには、垂直なスタックの中
にフィールドの一続きを入れて使います。全部を入れるにはテキ
ス ト が長すぎるとき、そうしたければ最後のフィールドを ...
で終らせることもできます。変数 $: を好きな文字のリストにす
ることで、テキストを分割する文字を変えることができます。
^ フィールドを使うと、可変長のレコードを生成するので、テキ
ストのフォーマットを短くしたいとき、チルダ (~) 文字を行 の
どこかに入れて空行を抑制することができます。 (可読性を高め
るため、普通はできれば行頭に入れるべきです。) チルダは出力
時には空白に変換されます。一つ目に続けて二つ目のチルダを書
くと、行中のすべてのフィールドがなくなるまで、その行を繰り
返 します。 (いろいろな @ のフィールドを使うとき、与える式
はいつも同じ値ではない方が良いでしょう。)
例:
# /etc/passwd ファイルの形式
format STDOUT_TOP =
Passwd File
Name Login Office Uid Gid Home
------------------------------------------------------------------
.
format STDOUT =
@<<<<<<<<<<<<<<<<<< @||||||| @<<<<<<@>>>> @>>>> @<<<<<<<<<<<<<<<<<
$name, $login, $office,$uid,$gid, $home
.
# バグレポート形式
format STDOUT_TOP =
Bug Reports
@<<<<<<<<<<<<<<<<<<<<<<< @||| @>>>>>>>>>>>>>>>>>>>>>>>
$system, $%, $date
------------------------------------------------------------------
.
format STDOUT =
Subject: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$subject
Index: @<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$index, $description
Priority: @<<<<<<<<<< Date: @<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$priority, $date, $description
From: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$from, $description
Assigned to: @<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$programmer, $description
~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$description
~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$description
~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$description
~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$description
~ ^<<<<<<<<<<<<<<<<<<<<<<<...
$description
.
同じ出力チャネルに対して、write を使って出力を混ぜることは
できますが、$- (ページの残り行数) を自分でいじらなければな
りません。
ほとんどが空白のフィールドがたくさんあるとき、レコード間で
reset 演算子を使うことを考えるべきです。効率的であるという
だけでなく、別のフィールドを加えてしまい、0 にし忘れてしま
うというバグを防ぐことができます。
プロセス間通信
perl の プロセス間通信(IPC)の能力は Berkeley のソケット機
構に基づいています。ソケットが無ければ、このセクションは無
視できます。この呼び出しは、同名のシステムコールに相当しま
すが、二つの理由で大抵引数は異なります。一つ目は、perl の
ファ イルハンドルは C ファイル記述子とは異なる動作をすると
いうことです。二つ目は、perl は文字列の長さを知っている の
で、その情報を渡さなくても良いということです。以下がクライ
アントのサンプル (未テスト) です:
($them,$port) = @ARGV;
$port = 2345 unless $port;
$them = 'localhost' unless $them;
$SIG{'INT'} = 'dokill';
sub dokill { kill 9,$child if $child; }
require 'sys/socket.ph';
$sockaddr = 'S n a4 x8';
chop($hostname = `hostname`);
($name, $aliases, $proto) = getprotobyname('tcp');
($name, $aliases, $port) = getservbyname($port, 'tcp')
unless $port =~ /^\d+$/;
($name, $aliases, $type, $len, $thisaddr) =
gethostbyname($hostname);
($name, $aliases, $type, $len, $thataddr) = gethostbyname($them);
$this = pack($sockaddr, &AF_INET, 0, $thisaddr);
$that = pack($sockaddr, &AF_INET, $port, $thataddr);
socket(S, &PF_INET, &SOCK_STREAM, $proto) || die "socket: $!";
bind(S, $this) || die "bind: $!";
connect(S, $that) || die "connect: $!";
select(S); $| = 1; select(stdout);
if ($child = fork) {
while (<>) {
print S;
}
sleep 3;
do dokill();
}
else {
while (<S>) {
print;
}
}
これがサーバ側です:
($port) = @ARGV;
$port = 2345 unless $port;
require 'sys/socket.ph';
$sockaddr = 'S n a4 x8';
($name, $aliases, $proto) = getprotobyname('tcp');
($name, $aliases, $port) = getservbyname($port, 'tcp')
unless $port =~ /^\d+$/;
$this = pack($sockaddr, &AF_INET, $port, "\0\0\0\0");
select(NS); $| = 1; select(stdout);
socket(S, &PF_INET, &SOCK_STREAM, $proto) || die "socket: $!";
bind(S, $this) || die "bind: $!";
listen(S, 5) || die "connect: $!";
select(S); $| = 1; select(stdout);
for (;;) {
print "Listening again\n";
($addr = accept(NS,S)) || die $!;
print "accept ok\n";
($af,$port,$inetaddr) = unpack($sockaddr,$addr);
@inetaddr = unpack('C4',$inetaddr);
print "$af $port @inetaddr\n";
while (<NS>) {
print;
print NS;
}
}
予約変数
次の変数名は、 perl にとって特別な意味があります。これらの
うち幾つかはアルファベットのシンボルにもしても良かったので
すが、 reset "a-zA-Z" で予約変数まで消されてしまうようなこ
とにしたくなかったのです。そのため、これらのおかしなシンボ
ル名に悩まされなければならないでしょう。そのうち多くは筋が
通ったニーモニック (記憶方法) で、シェルのものと類似になっ
ています。
$_ 入力およびパターン検索のデフォルト。次の組はそれぞ
れ同等です:
while (<>) {... # while の中でのみ同等
while ($_ = <>) {...
/^Subject:/
$_ =~ /^Subject:/
y/a-z/A-Z/
$_ =~ y/a-z/A-Z/
chop
chop($_)
(覚え方: 下線は実行されるとわかる。)
$. 最後に読み込まれたファイルハンドルの現在の行番号。
読み出し専用。明示的なファイルハンドルの close で
の み 行番号がリセットされることを覚えておいて下さ
い。 <> は明示的な close を行なわな い の で、ARGV
ファイル全部を通して行番号が増えていきます (eof の
例を参照して下さい)。 (覚え方: 多くのプログラム は
. を現在行番号の意味で使う。)
$/ 入力レコードの区切り文字。デフォルトは改行。ヌル文
字列にセットされると空行を区切りとして扱うことも含
め て、 awk の RS 変数と同じ働きをします。複数文字
にセットすると複数文字区切りにマッチさせることがで
きます。ファイルに空行が連続してあるとき、この変数
を "\n\n" にセットすると、"" にセットする場合と 少
々異なる意味を持つことに注意して下さい。 "" にセッ
トすると、二つかそれ以上の連続した空行を一つの空行
として扱います。 "\n\n" にセットすると、空行の後に
たとえ改行文字が続いていても、次の段落に含まれてい
る も のと盲目的に解釈されます。 (覚え方: / は詩を
クォートするとき行境界の区切りとして使える。)
$, print 演算子のための出力フィールド区切り文字。通常
は、print 演算子は単にコンマ区切りで指定したフィー
ルドを出力します。より awk に似た挙動をさせるた め
に は、フィールド間に出力する文字を指定する awk の
OFS 変数と同じものを、この変数をセットして下さい。
(覚え方: print文に , があるとき出力すべきもの。)
$"" $, と似ていますが、この変数の異なる点は、"" で囲ま
れた文字列 (または同様な挿入文字) に挿入される配列
値に適用されることです。デフォルトは空白文字です。
(覚え方: これは明白。)
$\ print 演算子の出力レコードセパレータ 文 字。 通 常
print 演算子は、後に改行やレコードセパレータ文字を
続いていないと推定して、単にコンマ区切りの指定フィ
ー ルドを出力します。より awk に似た挙動をさせるた
めには、print の終りに出力する文字を指定す る awk
の ORS 変数と同じものをこの変数にセットして下さ
い。 (覚え方: print の終りに \n を加える代わ り に
$\ をセット。) / にも似ていますが、 perl から "得
る" ものです。)
$# 数字の出力のための出力フォーマット。この変数は awk
の OFMT 変数を半分だけ受け継いでいます。しかし awk
と perl では、実際に何が数字であるかという概念の異
な ることがしばしばあります。初期値も、%.6g でなく
%.20g ですので、 awk の値を得るには、明示的 に $#
をセットする必要があります。 (覚え方: # は数字の記
号。)
$% 現在 select されている出力チャネルの現在のページ番
号。 (覚え方: % は nroff におけるページ番号。)
$= 現在 select されている出力チャネルの現在のページ長
(出力可能行)。デフォルトは 60。 (覚え方: = は平 行
線。)
$- 現在 select されている出力チャネルのページの残り行
数。 (覚え方: 1 ページの行数 - 出力済み行数)
$~ 現在 select されている出力チャネルの現在のレポート
フォーマット名。デフォルトは、ファイルハンドル名。
(覚え方: $^ の仲間。)
$^ 現在 select されている出力チャネルの現在のページ先
頭フォーマット名。デフォルトは、ファイルハンドル名
に "_TOP" を加えたもの。 (覚え方: 先頭ページ を 指
す。)
$| 0 でない値をセットすると、現在 select されている出
力チャネルに write や print が行なわれる毎にフラッ
シュします。デフォルトは 0。通常 STDOUT は、端末に
出力するときは行バッファが使われ、それ以外で は ブ
ロックバッファが使われることに注意して下さい。この
変数をセットするのは、 perl スクリプトを rsh の 基
で走らせている時等、パイプに出力している時に、出力
が起こる度に確認したい場合に便利です。 (覚え方: パ
イプを常に動かしておきたい。)
$$ perl が走らせているスクリプトのプロセス番号。 (覚
え方: シェルと同じ。)
$? 最後に close したパイプや (``) コマンド や system
演 算子の戻り値。これは、wait() システムコールが返
すステータスなので、サブプロセスの終了値は実 際 は
($? >> 8) です。プロセスを終了させたシグナルがあっ
た場合、$? & 255 はどのシグナルであるか、dump され
た core があるかどうかを返します。 (覚え方: sh や
ksh と同じ。)
$& 最後に成功したパターンマッチでマッチした文字列。 (
ブロック内や現在のブロックで閉じた eval でのマッチ
は含まれません。) (覚え方: あるエディタの & と 同
じ。)
$` 最後にパターンマッチに成功したパターンの前にある文
字列。 (ブロック内や現在のブロックで閉じた eval で
の マッチは含まれません。) (覚え方: ` は大抵クォー
トされた文字列の前。)
$' 最後にパターンマッチに成功したパターンの後ろにある
文 字列。 (ブロック内や現在のブロックで閉じた eval
でのマッチは含まれません。) (覚え方: ' は大抵 クォ
ートされた文字列の後。) 例:
$_ = 'abcdefghi';
/def/;
print "$`:$&:$'\n"; # abc:def:ghi を出力
$+ 最後に検索したパターンの最後の括弧にマッチします。
これは、複数候補のパターンマッチでどちらにマッチす
るかわからないときに便利です。例:
/Version: (.*)|Revision: (.*)/ && ($rev = $+);
(覚え方: 正で、前方を見ること。)
$* 文字列内で、複数行のマッチを行なうとき 1 をセット
し、パターンマッチの最適化の目的で、単一行を含む文
字 列であると perl に決め打ちにさせるときに 0 とし
ます。 $* が 0 のときに複数の改行を含む文字列の パ
タ ー ンマッチをすると、混乱した結果となります。デ
フォルトは 0。 (覚え方: * は複数のものにマッ チ す
る。) この変数は、^ や $ の解釈に影響するだけであ
るということに注意して下さい。改 行 の リ テ ラ ル
は、when $* == 0 としても検索できます。
$0 perl 起動したスクリプトのファイル名を保持していま
す。 $0 修飾子への代入は、ps(1) プログラムの引数の
部分を参照して下さい。 (覚え方: sh や ksh と同じ)
$<数字> 最後に行なったパターンマッチで対応する数字番目の括
弧のサブパターン。入れ子になったブロック内で既に終
了 したパターンマッチの数は含まれません。 (覚え方:
\数字と同じ。)
$[ 配列中の最初の要素や部分文字列の最初の文字の添字。
デ フォルトは 0 ですが、index() や substr() 関数の
添字のつけ方や評価に関して、 perl を awk (や For
tran) の動作にさせるには、この変数に 1 をセットす
ることでできます。 (覚え方: [ は添字の始まり。)
$] "perl -v" で出力される文字列。これは、perl イン タ
ープリタが正しいバージョンの範囲でスクリプトを実行
しているかどうかを決めるために、スクリプトの始めの
方で使われます。数値のコンテキストで使われると、バ
ージョン + パッチレベル / 1000 を返します。例:
# getcがつかえるかどうかを調べます
($version,$patchlevel) =
$] =~ /(\d+\.\d+).*\nPatch level: (\d+)/;
print STDERR "(No filename completion available.)\n"
if $version * 1000 + $patchlevel < 2016;
また、数値で使われると、
warn "No checksumming!\n" if $] < 3.019;
(覚え方: このバージョンの perl は right(正 し い、
右) 括弧に入ってるか? )
$; 多次元配列エミュレーションの際の添字の区切り。連想
配列の要素を次のように参照するとき、
$foo{$a,$b,$c}
実際には
$foo{join($;, $a, $b, $c)}
を意味しますが、
@foo{$a,$b,$c} # スライス--@ に注意
と書いてはいけません。
($foo{$a},$foo{$b},$foo{$c})
を意味することになってしまうからです。デフォルトは
"\034" で、 awk の SUBSEP と同じです。キーとしてバ
イナリデータを使うと、$; として安全な値はないだ ろ
うということに気をつけて下さい。 (覚え方: コンマ (
文法上添字の区切り) はセミコロンの半分。こ れ は、
ちょっ とひどいね。でも、$, は他のもっと重要なこと
に取られているので。)
$! 数値のコンテキストで使うと、通常の警告の文字列と共
に errono の現在の値を返します。 (これは、システム
エラーのような特別なエラーを除くと、$! の値に依 存
し た 動 作 をさせてはいけないということを意味しま
す。) 文字列のコンテキストで使うと、相当するシステ
ム エラー文字列を返します。 errno をセットするため
に $! に代入することができます。例えば、エラー番号
n に対して $! が文字列を返したいときや、 die 演算
子に終了値をセットしたいときなどです。 (覚え方: 一
体何が爆発したの? )
$@ 最 後に評価したコマンドからくる perl の文法エラー
メッセージ。ヌルなら、最後の評価が、正常に解析、実
行されたことになります (起動された演算は普通の形で
失敗したかもしれません)。 (覚え方: 文法エラーは ど
こに "アット (at where)" ?)
$< 現在のプロセスの実 uid。 (覚え方: setuid で走らせ
ているとき、*どこから* きた uid か。)
$> 現在のプロセスの実効 uid。例:
$< = $>; # 実効 uid に実 uid をセットします
($<,$>) = ($>,$<); # 実 uid と実効 uid を取り換えます
(覚え方: setuid で走らせているとき、* 行 く 先 の*
uid。) 注意: $< と $> は setreuid() をサポートして
いるマシンでだけ交換できます。
$( 現在のプロセスの実 gid。同時に複数グループのメンバ
となることをサポートしたマシンで、属しているグルー
プの空白区切りのリストが得られます。最 初 の 数 は
getgid() の返すもので、残りが getgroups() の返すも
のです。残りの中には最初の数値と同じものも含まれて
い るかもしれません。 (覚え方: 括弧は GROUP に使わ
れる。 setgid スクリプトを走らせているとき、実 gid
は LEFT(残っている、左) のグループ。)
$) 現在のプロセスの実効 gid。同時に複数グループのメン
バとなることをサポートしたマシンで、属しているグル
ー プ の空白区切りのリストが得られます。最初の数は
getegid() の返すもので、残りが getgroups() の返 す
ものです。残りの中には最初の数値と同じものも含まれ
ているかもしれません。 (覚え方: 括弧は GROUP に 使
われる。 setgid スクリプトを走らせているとき、実効
gid はあなたの RIGHT(正しい、右の)グループ。)
注意: $<, $>, $(, $) は、相当する set[re][ug]id()
ルーチンをサポートしているマシンでだけセットできま
す。 $( と $) は setregid() をサポートしているマシ
ンでだけ交換できます。
$: format の (^ で始まる) 継続フィールドを埋めるよう
に文字列を分ける際の直前の文字列セット。デフォルト
は " \n-" で、空白やハイフンで分けられます。 (覚え
方: 詩では "コロン" は行の一部)
$^D デバッグフラグの現在の値。 (覚え方: -D スイッチ の
値。)
$^F 最 大システムファイル記述子数。通常は 2。システム
ファイル記述子は、子プロセスに渡されますが、それよ
り数字が上のファイル記述子は渡されません。 open す
る間は、たとえ open に失敗したとしても、シス テ ム
ファイル記述子は保存されます。 open が試みられる前
に、通常の記述子は close されます。
$^I ファイルをその場で変更する場合の拡張子の値。その場
で 変更できないようにするには、この変数を undef し
ます。 (覚え方: -i スイッチの値)
$^L 改ページするために出力するフォーマット。デフォルト
は \f です。
$^P デバッガが、自分自身をデバッグしないためにクリアす
る内部フラグ。これをクリアしておくと、デバッグを不
可能にさせられると考えられます。
$^T スクリプトが走り始めた時刻を、epoch からの秒で保持
します。 -M , -A , -C ファイルテストで返され た 値
は、この変数の値に基づいています。
$^W 警告スイッチの現在の値。 (覚え方: -w スイッチに関
係する。)
$^X argv[0] から来る、起動された perl 自身の名前。
$ARGV <> から読み込んでいるとき、読み込み中のファイル 名
を保持します。
@ARGV 配列 ARGV は、スクリプトに渡されたコマンドライン引
数を保持します。 $ARGV[0] はコマンド名ではなく、最
初 の引数なので、$#ARGV は一般に引数の数 -1 です。
コマンド名については、$0 を参照して下さい。
@INC 配列 INC は、 perl スクリプ ト が "do EXPR" や
"require" で評価されるときに探されるべきディレクト
リのリストを保持します。初期値として、 -I コマンド
ラ インスイッチの引数、これに続きデフォルトの perl
ライブラリ (おそらく "/usr/share/perl")、これに 続
きカレントディレクトリを示す "." です。
%INC 連想配列 INC は、"do" や "require" を介してインク
ルードされる各ファイル名のためのエントリを含んでい
ます。キーは、指定したファイル名で、値は実際にファ
イルが見つ かっ た 位 置 の 値 で す。 こ の 配 列
は、"require" コマンドが与えるファイルが既にインク
ルード済みかどうかを決めるのに使われます。
$ENV{expr}
連想配列 ENV は、現在の環境変数を保持していま す。
ENV へ値を設定すると、子プロセスの環境が変わりま
す。
$SIG{expr}
連想配列 SIG は、各シグナルハンドラをセットする の
に使われます。例:
sub handler { # 第一引数はシグナル名
local($sig) = @_;
print "Caught a SIG$sig--shutting down\n";
close(LOG);
exit(0);
}
$SIG{'INT'} = 'handler';
$SIG{'QUIT'} = 'handler';
...
$SIG{'INT'} = 'DEFAULT'; # デフォルト動作に戻す
$SIG{'QUIT'} = 'IGNORE'; # SIGQUIT を無視する
SIG 配 列は、perl スクリプトで実際にシグナル用に
セットされた値を保持しています。
パッケージ
perl は、パッケージ間で異なる名前空間持つメカニズムを用 意
しており、各々の変数がぶつからないように、パッケージを守っ
ています。デフォルトで、perl スクリプトはパッケージ "main"
と してコンパイルを始めます。 package 宣言を使うことによっ
て、名前空間を切り替えることができます。パッケージ宣言の有
効 範 囲は、宣言それ自身から、閉じたブロックの終端までです
(local() 演算子と同じ有効範囲)。普通 "require" 演算子に よ
りインクルードされたファイルの中の最初の宣言として使われま
す。複数箇所で同一パッケージに入ることが出来ます; ブロック
中でコンパイラがどのシンボルテーブルを使うかに影響するだけ
です。他のパッケージの変数やファイルハンドルは、識別子の前
にパッケージ名とシングルクォートを付けることで、参照できま
す。パッケージ名がヌルの場合、"main" と解釈されます。
文字で始まる識別子は、パッケージシンボルテーブルに保存され
ます。それ以外のすべてのシンボルは、パッケージ "main" に保
持されます。更に、識別 子 STDIN, STDOUT, STDERR, ARGV,
ARGVOUT, ENV, INC, SIG は、たとえ組み込みの変数、関数と異
なる目的で使われたとしても、強制的にパッケージ "main" に属
す る ものとして扱われます。仮に、"m", "s", "y" と呼ばれる
パッケージを持っていたとすると、パターンマッチ、代入、変換
として解釈されるので、識別子を適した形で使うことができない
ことに注意しましょう。
eval された文字列は、eval がコンパイルされたパッケージ内で
コンパイルされます。 (しかし、$SIG{} への代入は、main パッ
ケージで指定されたシグナルハンドラと解釈されます。パッケー
ジ内でシグナルハンドラを持ちたい場合、シグナルハンドラ名を
適切に指定して下さい。) 例えば、perl ラ イ ブ ラ リ 内 の
perldb.pl を調べてみましょう。これは始めに DB パッケージに
切り替わり、デバッガがデバッグしようとしているスクリプト内
の変数を変更しないようになっています。しかし、いろいろな時
点で、main パッケージのコンテキストのいろいろな式を評価 す
る た めに、これは main パッケージに一時的に戻って来ていま
す。
パッケージのシンボルテーブルは、パッケージ名の前に下線のつ
いた連想配列に蓄えられることになります。連想配列の各エント
リの値は、*name 表記を使うときに参照しようとしているものに
なります。実際、次の例は同じ効果 (もちろん main パッケージ
の場合) がありますが、最初のものの方がコンパイル時にシンボ
ルテーブルを見るので、より効率が良くなります:
local(*foo) = *bar;
local($_main{'foo'}) = $_main{'bar'};
例 え ば、以下によりパッケージ内のすべての変数を出力できま
す。これは perl ライブラリの dumpvar.pl から取っています:
package dumpvar;
sub main'dumpvar {
($package) = @_;
local(*stab) = eval("*_$package");
while (($key,$val) = each(%stab)) {
{
local(*entry) = $val;
if (defined $entry) {
print "\$$key = '$entry'\n";
}
if (defined @entry) {
print "\@$key = (\n";
foreach $num ($[ .. $#entry) {
print " $num\t'",$entry[$num],"'\n";
}
print ")\n";
}
if ($key ne "_$package" && defined %entry) {
print "\%$key = (\n";
foreach $key (sort keys(%entry)) {
print " $key\t'",$entry{$key},"'\n";
}
print ")\n";
}
}
}
}
たとえサブルーチンがパッケージ dumpvar でコンパイルされ る
としても、サブルーチン名がパッケージ "main" に挿入されるよ
うに、サブルーチン名の前にパッケージ名をつけなければならな
いことに注意して下さい。
スタイル
各々のプログラマは、フォーマットに関してもちろん自分自身の
好みがあるでしょうが、自分のプログラムを読み易くするための
一般的なガイドラインがあります。
1. あることを特別な方法で*できる*からといって、そうしなけ
ればならないということはありません。 perl は、一つのこ
とをするときに、幾つかの方法があるように設計されている
ので、最も読み易いものを選ぶように考えて下さい。例えば
open(FOO,$foo) || die "Can't open $foo: $!";
は、
die "Can't open $foo: $!" unless open(FOO,$foo);
よりも良いです。なぜなら、後者の方法は文の主題を修飾子
内に隠しているからです。一方、
print "Starting analysis\n" if $verbose;
は
$verbose && print "Starting analysis\n";
より良いです。主となるのは、ユーザが -v を打ったかどう
かではないからです。
同 様 に、演算子がデフォルトの引数を仮定しているからと
いって、それはデフォルトを用いなければならないというこ
とではありません。デフォルトというものは、ちょっとした
プログラムを書く、怠け者のシステムプログラマのためにあ
ります。読み易いプログラムをしたければ、引数を付けるよ
うにして下さい。
同じようなこととして、あちこちで括弧を省略 できると い
うことは、以下のように書けということではありません:
return print reverse sort num values array;
return print(reverse(sort num (values(%array))));
疑わしいときは、括弧をつけて下さい。もしかすると、物好
きな輩が、vi で % キーを叩くかもしれません。
たとえ疑わしくなかったとしても、自分の後でそのコードを
管理する人間の精神衛生上好ましいですし、その人が間違っ
たところに括弧をつける可能性も大いにあります。
2. 無理にこじつけて、ループの先頭や終わりで終了しようとし
ないで下さい。 perl には、真ん中からでも抜けられるよう
に "last" 演算子が用意されているのですから。少々はみ出
しても、より見易くなるようにして下さい:
line:
for (;;) {
statements;
last line if $foo;
next line if /^#/;
statements;
}
3. ループラベルを使うのを恐がらないで下さい--多重ループの
抜けだしができるようにするためだけでなく、可読性を高め
るためにあるのですから。最後の例を参照して下さい。
4. 可搬性のため、すべてのマシンには実装されていない機能を
使うときは、失敗しないかどうか、eval の中で構成を確 か
めてみて下さい。どのバージョンやパッチレベルで特定の仕
様が実装されているかを知っているなら、$] を調べて、 実
装されているかどうかを確認できます。
5. 覚え易い識別子を選んで下さい。
6. 一貫性を持たせましょう。
デバッグ
perl に -d スイッチを付けて起動すると、デバッグモニタの基
でスクリプトが走ります。最初の実行文の前で一時停止し、以下
のようなコマンド入力を促します:
h ヘルプメッセージを出力する。
T スタックトレース。
s シングルステップ。次の文の始めに達するまでを実
行します。
n 次。サブルーチンコール内では止まらずに、次の文
に達するまで実行します。
f 終了。現在のサブルーチンが終了するまで、文を実
行し続けます。
c 継続。次のブレークポイントに達するまで実行しま
す。
c line 指定した行まで実行します。指定した行に、一回き
りのブレークポイントを挿入します。
<CR> 最後に実行した n または s を繰り返します。
l min+incr min 行目から incr+1 行を表示します。 min を 省
略 す る と、 最後に表示した残りから始めます。
incr を省略すると、前回の incr 値が使 わ れ ま
す。
l min-max 指定範囲内の行を表示します。
l line 指定行を表示します。
l 次のウィンドウを表示します。
- 前のウィンドウを表示します。
w line その行と前後のウィンドウを表示します。
l subname サブルーチンを表示します。長いサブルーチンの場
合は、始めの方だけを表示します。それ以上表示す
るには、"l" を使って下さい。
/pattern/ 正規表現の前方検索。最後の / は省略可能です。
?pattern? 正規表現の後方検索。最後の ? は省略可能です。
L ブレークポイントまたはアクションの設定された行
を表示します。
S すべてのサブルーチン名を表示します。
t トレースモードを on/off するトグル。
b line condition
ブレークポイントをセットします。 line を省略す
る と、 実行されようとしている行にセットされま
す。 condition が指定されると、ブレークポイ ン
トの文に達する毎に condition が評価され、 con
dition が真のときだけブレークします。ブレー ク
ポイントは実行文の先頭にだけセットできます。
b subname condition
ブレークポイントをサブルーチンの最初の実行文に
セットします。
d line ブレークポイントを削除します。 line を省略する
と、実行しようとしている行のブレークポイントが
削除されます。
D すべてのブレークポイントを削除します。
a line command
行にアクションをセットします。バックスラッシュ
の直後に改行すれば、複数行コマンドも入力できま
す。
A すべての行のアクションを削除します。
< command デバッガがプロンプトを出す前に実行するアクショ
ンをセットする。バックスラッシュの直後に改行す
れば、複数行コマンドも入力できます。
> command コマンドを入力してスクリプト実行に移る時に、プ
ロ ン プトの後に実行するアクションをセットしま
す。バックスラッシュの直後に改行すれば、複数行
コマンドも入力できます。
V package パッ ケージ内のすべての変数をリストします。デ
フォルトは、メインパッケージです。
! number デバッグコマンドの再実行を行ないます。 number
が省略されると、直前のコマンドを再実行します。
! -number 幾つか前のコマンドを再実行します。
H -number 最後の n 個のコマンドを表示します。 1 文字より
長いコマンドをリストします。 number を省略する
と、すべてをリストします。
q or ^D 終了します。
command コマンドを perl の文として実行します。足りない
セミコロンは補われます。
p expr "print DB'OUT expr" と同じことです。 DB'OUT
ファイルハンドルは、どこに STDOUT がリダイレク
ト されているかに関わらず、/dev/tty にオープン
されます。
デバッガを変更したいときは、perldb.pl ファイルを perl のラ
イブラリから、カレントディレクトリにコピーして、必要に応じ
て修正して下さい。 (コマンドラインに -I. を付けなければ な
ら ないでしょう。) 初期化コードを含む .perldb ファイルを設
定することで、カスタマイズができます。例えば、以下のような
エイリアスを作ることができます:
$DB'alias{'len'} = 's/^len(.*)/p length($1)/';
$DB'alias{'stop'} = 's/^stop (at|in)/b/';
$DB'alias{'.'} =
's/^\./p "\$DB\'sub(\$DB\'line):\t",\$DB\'line[\$DB\'line]/';
setuid スクリプト
perl は、安全な setuid スクリプトや setgid スクリプトを簡
単に書けるようにデザインされています。スクリプトの各行が何
回も置換されるシェルとは違って、 perl は、隠された "わけの
判らないもの" を少なくして、より伝統的な評価機構を使ってい
ます。それに加え、この言語は組み込み機構をより多く備えてい
て、目的を達成するために外部の (すなわち信頼できない可能性
がある) プログラムに頼らなければならないことは、ほとんどあ
りません。
パッチが当たっていない 4.2 または 4.3bsd カーネ ル で は、
setuid スクリプトは本質的に危険をはらんでいますが、このカ
ーネルの機能は無効にできます。この場合、 perl スクリプトに
( 無 意 味 な) setuid/gid ビットが付いていると、 perl は
setuid と setgid 機構をエミュレートできます。カーネルの 機
能が無効でない場合、 perl は setuid スクリプトが安全でない
ことをうるさく訴えるでしょう。カーネルの setuid スクリプト
機 能を無効にするか、そうでなければスクリプトに C のラッパ
をかぶせる必要があるでしょう。
perl が setuid スクリプトを実行しているとき、明ら か な ト
ラップにはまらないように特別な注意を払います。 (いくつかの
点で、perl スクリプトは同等の C プログラムより安全で す。)
コ マンドライン引数と環境変数と入力は、"汚れ" とみなされ、
サブシェルを起動するコマンドや、ファイル、ディレクトリ、プ
ロセスを変更するようなコマンドの中では、直接にも間接的にも
使われません。それ以前に汚れた値を参照したような式の 中 で
セットされた変数も、また汚れていることなります。 (汚れた値
が変数に影響することが、たとえ論理的に不可能だとしても)
例えば:
$foo = shift; # $foo は汚れています
$bar = $foo,'bar'; # $bar も汚れています
$xxx = <>; # 汚れています
$path = $ENV{'PATH'}; # 汚れていますが、以下を見て下さい
$abc = 'abc'; # 汚れていません
system "echo $foo"; # 危険です
system "/bin/echo", $foo; # 安全です (shを使わないので)
system "echo $bar"; # 危険です
system "echo $abc"; # PATH がセットされるまで、
# 安全ではありません
$ENV{'PATH'} = '/bin:/usr/bin';
$ENV{'IFS'} = '' if $ENV{'IFS'} ne '';
$path = $ENV{'PATH'}; # 汚れていません
system "echo $abc"; # もはや汚れていません!
open(FOO,"$foo"); # OK
open(FOO,">$foo"); # 駄目です
open(FOO,"echo $foo|"); # 駄目だけど..
open(FOO,"-|") || exec 'echo', $foo; # OK
$zzz = `echo $foo`; # 危険。 zzz は汚れています。
unlink $abc,$foo; # 危険
umask $foo; # 危険
exec "echo $foo"; # 危険
exec "echo", $foo; # 安全 (sh を使いません)
exec "sh", '-c', $foo; # 安全と見なされてしまう、嗚呼
汚れは、各スカラ値と関係するので、配列の要素は汚れているも
のも、汚れていないものもあります。
何か安全でないことをしようとすると、 "Insecure dependency"
とか "Insecure PATH" というような致命的エラーになりま す。
それでも、危険なシステムコールや exec を書くことができます
が、上記の最後の例のようなことを明示的に行なった場合に限る
ということを覚えておいて下さい。サブパターンを参照すること
でも、汚れの機構を避けることができます --perl は、$1, $2
などを使った部分文字列の参照では、自分のしていることを知っ
ているはずだと解釈します。次のようなパターンの場合です:
$ARGV[0] =~ /^-P(\w+)$/;
$printer = $1; # 汚れていません
これは、\w+ がシェルのメタキャラクタにマッチしないので、ま
ず安全です。 .+ を使うと危険でしょうが、 perl はそこまで調
べないので、パターン指定には注意を払うべきです。こ れ は、
ファイル操作をしたいときに ($> を $< と同じにしなければ)、
ユーザが与えるファイル名を汚さないための唯一の機構です。
汚れた値を使うことを気にしないような他の操作でもトラブルを
起こす場合があります。ユーザが与えたファイル名を扱うファイ
ルテストは、慎重に使って下さい。できれば、$> = $< というよ
うにセットした後で open して下さい。 perl では、汚れたファ
イルをオープンして読みだすことが制限されないので、出力する
内容については注意して下さい。汚れの機構は、ばかな間違いを
防ぐように作られているのであって、考える必要がなくなるよう
にするためではありません。
環境
HOME chdir に引数がないときに使われます。
LOGDIR chdir に引数が無く、HOME がセットされていない
ときに使われます。
PATH サブプロセスを実行するとき、および -S が使われ
たときはスクリプトを探す際に使われます。
PERLLIB 標 準ライブラリやカレントディレクトリを見る前
に、perl ライブラリファイルを探すディレクト リ
のコロン区切りのリストです。
PERLDB デバッガコードを得るのに使われるコマンドのこと
です。セットされていないと、
require 'perldb.pl'
を使います。
これらを別にすると、 perl は、スクリプト実行時と子プロセス
に 渡された環境変数しか使いません。しかし、setuid で走って
いるスクリプトは、だまされないようにするために何より先に以
下の行を実行しておいた方が良いでしょう:
$ENV{'PATH'} = '/bin:/usr/bin'; # 必要なパスを入れましょう
$ENV{'SHELL'} = '/bin/sh' if $ENV{'SHELL'} ne '';
$ENV{'IFS'} = '' if $ENV{'IFS'} ne '';
作者
Larry Wall <lwall@netlabs.com>
MS-DOS への移植 Diomidis Spinellis <dds@cc.ic.ac.uk>
関連ファイル
/tmp/perl-eXXXXXX -e コマンドのためのテンポラリファイル
関連項目
a2p awk から perl への変換プログラム
s2p sed から perl への変換プログラム
診断
コンパイルエラーは、エラーの行番号と次にあるべきトー ク ン
か、または調べられたトークンの型を教えてくれます。 ( -e ス
イッチで perl に渡されたスクリプトの場合、各 -e が一行に数
えられます。)
setuid スクリプトには、更に "Insecure dependency" のような
エラーメッセージを生じるという制約があります。 setuid スク
リプトのセクションを参照して下さい。
トラップ
awk に慣れたユーザは、以下のことに特に注意を払わなければな
りません:
* perl では、(ブロックの終わりを除く) すべての単文の後に
セミコロンが必要です。改行は文の区切りではありません。
* if や while には、中括弧 {} が必要です。
* perl では、変数は $ か @ で始まります。
* 配列の添字は、$[ をセットしなければ 0 で始まり ま す。
substr() と index() の文字位置も同様です。
* 配列の添字が数字であるか文字列であるかを決めなければな
りません。
* 連想配列は、参照するだけでは存在することになりません。
* 比較の際には、文字列比較か、数値比較かを決めなければな
りません。
* 入力行を読み込んだだけでは、split は行なわれません。自
分 で split して、配列に入れなければなりません。そし
て、 split 演算子は、異なる引数を取ります。
* 現在の入力行は、通常 $0 ではなく $_ です。一般に改行コ
ー ド は 除かれません。 ($0 は実行されたプログラム名で
す。)
* $<数字> は、フィールドの参照ではありません--最後にマッ
チしたパターンの部分文字列を参照します。
* print 文は $, と $\ を設定しなければ、フィールド区切り
やレコード区切りを出力しません。
* ファイルに出力する前には、オープンしなければなり ま せ
ん。
* 範囲演算子は ".." であって、コンマではありません。 (コ
ンマ演算子は、C と同じ動作です。)
* マッチ演算子は、"~" でなく "=~" です。 ("~" は C と 同
じく補数の演算子です。)
* 指数演算子は、"^" でなく "**" 演算子です。 ("^" は、C
と同じく XOR 演算子です。)
* 結合演算子は "." であり、ヌル文字列ではありません。 (
ヌル文字列を使うと 3 番目の / が除算演算子と解釈される
ため、 "/pat/ /pat/" が解析不能になります。--トーク ン
解 析は、実際のところ /, ?, < のような演算子ではコンテ
キストにやや敏感です。そして、実は、. 自身は数字の始め
になり得ます。)
* next, exit, continue の動作は異なります。
* 次の変数の動作は異なります。
Awk Perl
ARGC $#ARGV
ARGV[0] $0
FILENAME $ARGV
FNR $. - 何か
FS (何でもよい)
NF $#Fld かそのようなもの
NR $.
OFMT $#
OFS $,
ORS $\
RLENGTH length($&)
RS $/
RSTART length($`)
SUBSEP $;
* 疑わしいときは、 awk のプログラムを a2p に通して、出て
来たもの見て下さい。
C に洗脳されたプログラマは、次のことを特に心に留めておかな
ければなりません:
* if や while には、中括弧 {} が必要です。
* "else if" でなく、"elsif" を使わなければなりません。
* break や continue は、それぞれ last や next になりま
す。
* switch 文はありません。
* perl では、変数は $ か @ で始まります。
* printf には * は実装されていません。
* コメントは、/* でなく # で始まります。
* 何者のアドレスを得ることもできません。
* ARGV は大文字でなければなりません。
* link, unlink, rename 等のシステムコールは、成功時に 0
でなく、非 0 を返します。
* シグナルハンドラは、数字ではなくシグナル名を扱います。
経験豊かな sed プログラマは、次のことを心に留めておかな け
ればなりません:
* 置換の後方参照では、\ でなく $ を使います。
* パターンマッチメタキャラクタ (, ), | の前にはバックス
ラッシュをつけません。
* 範囲演算子は、コンマでなく .. です。
鋭い shell プログラマは、次のことを心に留めておかなけれ ば
なりません:
* `` 演算子のコマンド内では、'' にくくられていないと変数
置換が行なわれます。
* `` 演算子は csh と違って、戻り値の変換をしません。
* シェル (特に csh) は、各コマンド行で複数レベルの置換を
行 ないます。 perl は、"", ``, <>, // のような決まった
構造においてのみ、置換が行なわれます。
* シェルは、スクリプトを一度に少しだけ解釈します。 perl
は、すべてのプログラムを実行前にコンパイルします。
* 引 数は、$1, $2,.. ではなく、@ARGV を介して利用できま
す。
* 環境は、変数として自動的に利用可能とはなりません。
訂正と追加
perl の本、 Programming Perl には以下のような省略と抜け が
あります。
5 ページの例
eval "/usr/bin/perl
は、以下でなければいけません。
eval "exec /usr/bin/perl
195 ページの System V の sum 相当のプログラムは、極めて小
さなファイルでしか動作しません。大きなファイルでは、以下を
使って下さい。
undef $/;
$checksum = unpack("%32C*",<>) % 32767;
alarm と sleep に関する記述は、シグナル SIGALARM と言って
いますが、 SIGALRM でなければなりません。
$/ の初期値をセットする -0 スイッチは、この本が出 版 後 に
perl に追加されました。
-l スイッチでは、自動行末処理を行なうようになっています。
qx// 構造は バックスラッシュ `` と同義です。
$0 は、 ps (1) の引数表示を変更するために、代入可能となり
ました。
新しい @###.## フォーマットは、フォーマットの記述から偶 然
省略されました。
s///ee が置換式の多重評価を生じることが、出版時に知られて
いませんでした。これは、仕様と解釈されるべきです。
(LIST) x $count は、配列の繰り返しを実行します。
正規表現には、括弧の数に制限がなくなっています。
ダブルクォート "" のコンテキストでは、更に以下のエスケープ
がサポートされています: \e, \a, \x1b, \c[, \l, \L, \u, \U,
\E 最後の 5 つの制御コードは、大文字小文字の変換です。
$/ 変数には、複数の区切り文字をセットできます。
通常のパターンマッチに g 修飾子が使えます。これにより、 文
字列から複数のマッチを検索することで、パターンマッチを繰り
返します。
$^T を除いて、すべての $^X 変数が増えています。
FILEHANDLE に対するデフォルトのページ先 頭 フォ ー マッ ト
は、top でなく FILEHANDLE_TOP になっています。
eval {} と sort {} 構造は、version 4.018 で追加されまし
た。
pack と unpack の v と V (リトルエンディアン) テンプレート
オプションは、 vertion 4.019 で追加されました。
バグ
perl 型のキャスト、atof()、sprintf() のようないろいろな操
作は、マシンの定義に左右されます。
あるストリームで、stdio が各 read や write の間に seek や
eof を 必 要とする場合、 perl はそのようにします。 (これ
は、sysread() と syswrite() には適用されません。)
どの組み込みデータタイプも勝手なサイズ制限は持っていません
( メモリサイズは別です) が、それでもいくらかは限界はありま
す: 識別子は 255 文字以上にはできませんし、 -S を 使 う と
き、PATH の要素は 255 を超えてはいけません。正規表現は、内
部的に 32767 バイトを超えられません。
perl は、実は病理学的折衷主義のがらくたリスター (Patholog
ically Eclectic Rubbish Lister) なんですが、私がそう言った
とは誰にも話さないで下さい。
3rd Berkeley Distribution PERL(1)