◆ Perl の文法

◇ 基礎知識

それぞれの行を statement と呼ぶ。statement の末尾には「;」(セミコロンをつける)。statement は上から順番に実行されていく。通常の変数には $ を付けて表わす。数値は以下の形式を使用できる。

  • 12345:整数
  • 12_345:整数(アンダーバーは無視される)
  • 123.45:小数
  • 1.23E45:指数
  • 012345:8進数
  • 0x12345:16進数

文字列はダブルクォーテーション、またはシングルクォーテーションで囲む。ダブルクォーテーションの中では変数やバックスラッシュが評価されるが、シングルクォーテーションの中では純粋な文字として認識される。

$str = "SevenKey";
print ">$str\n";
print '>$str\n';
>SevenKey
>$str\n

変数名にはアンダーバーを含む半角英数文字を使用することができるが、最初の1文字は数値であってはならない

(駄目例)
$seven-key
$7key

perlでは、数値と文字列の扱いはあいまいで、その都度数値として評価されたり、文字列として評価されたりする。

真偽判断では、(""), (0), ("0")は偽として、それ以外は真として扱われる。truefalse という特殊な変数がある訳ではなく、return(false) は、"false" という文字列を返すだけである。真偽を返却する関数を評価する際は if (&samp()){} と評価する。

変数には定義済みの状態と未定義の状態がある。最初は未定義だが、最初に何か値が代入されると定義済みになる。定義済みかどうかを調べるためには defined()を使用する。

perlには省略の美学というものがあり、いろいろな場面で変数名を省略することができる。省略した場合は、$_ を指定したものとみなされる。

while (<IN>)

while ($_ = <IN>)

print;

print $_;

/^From:/

$_ =~ /^From:/

while () {
    if (/^From:/) { print; }
}
while ($exp = ) {
    if ($exp =~ /^From:/) { print $exp; }
}

◇ 演算子

算術演算子

$lng = 7 + 3;
$lng = 7 - 3;
$lng = 7 * 3;
$dbl = 7 / 3;
$lng = 7 % 3;
余(=1)
$lng = 7 ** 3;
乗(=343)
$lng++;
$lng = $lng + 1
$lng--;
$lng = $lng - 1

ビット演算子

$strX | $strY
$strX と $strY のOR
$strX & $strY
$strX と $strY のAND
~$strX
$strXのビットをすべて反転させる
$strX << 2
$strX を2ビット左シフト
$strX >> 2
$strX を2ビット右シフト

数値比較演算子

if ($lngX == $lngY)
$lngX と $lngY が等しいとき
if ($lngX != $lngY)
$lngX と $lngY が等しくないとき
if ($lngX <= $lngY)
$lngX が $lngY より等しいか小さいとき
if ($lngX >= $lngY)
$lngX が $lngY より等しいか大きいとき
if ($lngX < $lngY)
$lngX が $lngYより小さいとき
if ($lngX > $lngY)
$lngX が $lngY より大きいとき
if (($lngX==2) && ($lngY==7))
$lngX が 2 且つ、$lngY が 7 であれば
if (($lngX==2) || ($lngY==7))
$lngX が 2 又は、$lngY が 7 であれば
if ($lngX <=> $lngY)
比較結果を -1, 0, 1 のいずれかで返す

文字列比較演算子

if ($strX eq $strY )
$strX と $strY が等しいとき
if ($strX ne $strY )
$strX と $strY が等しくないとき
if ($strX le $strY )
$strX が $strY より等しいか小さいとき
if ($strX ge $strY )
$strX が $strY より等しいか大きいとき
if ($strX lt $strY )
$strX が $strY より小さいとき
if ($strX gt $strY )
$strX が $strY より大きいとき
if ($strX =~ /KEY/)
$strX が KEY という文字を含むとき
if ($strX !~ /KEY/)
$strX が KEY という文字を含まないとき
if ($strX cmp $strY )
比較し、-1, 0, 1 のいずれかで返す

範囲演算子

@samp = (1 .. 5);
@samp = (1, 2, 3, 4, 5); と同様
for (1 .. 5)
for ($_ = 1; $_ <= 5; $_++) と同様

反復演算子

print 'K' x 5;
KKKKK
$str x= 5;
$str を 5 回繰り返したものを $str に代入
@samp = (K) x 5;
(K, K, K, K, K)同様

文字列連結

$strX = $strY . $strZ;
文字列 $strY と 文字列 $strZ を連結する
$strX .= $strY;
$strX = $strX . $strY と同様です

◇ スカラー変数

( $ )で始まる変数はスカラー変数と呼ばれる。スカラー変数には数値又は文字列を一つ代入することができる。通常、初期化していない変数は NULL または 0 として扱われるが、処理系によっては誤動作を起こすことがあるらしいので最初に $lng = 0; と初期化しておいた方がよい

$samp = 7;
$samp = 'Key';

◇ 配列

配列は $変数名[添え字]という形式で個々の要素を操作したり、( @ )を用いて配列全体を操作したりすることができる。添え字には正の整数値(0 含む)を指定する。配列同士の一括代入も可能である

$sampX[0] = 7;
$sampX[1] = 'Key';
( $year, $mon, $day ) = ( 1977, 7, 7 );

@samp = ( 'a', 'b' );
$samp[2] = 'c';
@samp[3..4] = ( 'd', 'e' );
print @samp;

>a b c d e

$#exp は、@exp の配列の最後の添え字(個数から1をひいたもの)を表わす

@samp = ( 'a', 'b', 'c', 'd', 'e');
print "$#samp\n";

>4

()は空配列を示す。

@samp = ();

配列を操作するための関数

shift(@exp);
最初の要素を取り除き、これを返す
pop(@exp);
最後の要素を取り除き、これを返す
push(@exp, $samp);
最後に要素を追加する
push(@exp1, @exp2);
@exp1 の後ろに @exp2 の要素を追加する
splice(@exp, 3, 2);
$exp[3..4](2個)を取り除き、これを返す
reverse(@exp);
@exp の要素を逆順にしたものを返す
sort(@exp);
@exp の要素をソートした結果を返す
@exp = split(/<>/, $samp);
文字列 $samp を"<>"で分割し、その配列を返す

(追記)

#すべての配列要素について処理を行う
foreach $i (@exp) {
    print "$i\n";
}

◇ 連想配列

$変数名{文字列}という形式で、文字列を添え字とした配列を操作できる。%変数名 という形式で、連想配列全体を操作できる。

$exp{"Jan"} = "1st";
$exp{"Feb"} = "2nd";
%exp = ( "Jan", "1st", "Feb", "2nd" );

(追記)

#すべての連想配列要素について処理を行う
while (($name, $value) = each(%xx)) {
   }

◇ 環境変数

%ENVという特別な連想配列変数を用いて環境変数の値を読み取ったり設定したりすることができる。

ウェブサーバ情報に関する環境変数リスト
GATEWAY_INTERFACEサーバが使用するCGIのレビジョン情報
SERVER_ADMINウェブサーバ管理者のメールアドレス情報
SERVER_NAMEサーバのホスト名、ドメイン名、またはIPアドレス情報
SERVER_PORTリクエスト送信に使われたポート番号
SERVER_PROTOCOLリクエスト送信に使われたプロトコルの名前とレビジョン情報
SERVER_SOFTWARECGI プログラム を起動したサーバソフトウエアの名前とバージョン情報
CGI 環境の情報に関する環境変数のリスト
CONTENT_LENGTHPOSTから標準入力に送信されたデータのバイト数
CONTENT_TYPEPOSTとPUTなどのクエリに添付されたデータのMIMEタイプ
DOCUMENT_ROOT実行されているスクリプトの仮想パス
PATHUNIXコマンドを起動するディレクトリ
PATH_ INFOクライアントから送られるエキストラパス情報
PATH_TRANSLATEDウェブサーバのドキュメントルートに環境変数PATH_INFOを追加した情報
QUERY_STRINGクエリとして送られたURL情報のクエスチョン以降の情報
データはURLエンコードされている
REQUEST_METHODリクエスト送信方法(GETやPOSTなど)
SCRIPT_FILENAMECGI プログラムのファイル名も含めた絶対パス情報
SCRIPT_NAMECGI プログラムのルートディレクトリ以降のパス情報
クライアントに関する環境変数のリスト
AUTH_TYPEユーザを認証するときに使用する認証メソッド
ウェブサーバとリモートホストがユーザ認証プロトコルを実行しているときだけ値がある
PATH_TRANSLATEDCGIプログラムに渡されるエキストラパス情報
HTTP_FROMリクエストを出しているユーザの電子メールアドレス
ほとんどのブラウザでは、この変数をサポートしていない
HTTP_ACCEPTクライアントが受け付けることができるMIMEタイプのリスト
HTTP_USER_AGENTクライアントがリクエストを発行するときに使用するブラウザ名
HTTP_REFERER呼び出し元のURL
アドレスバーからの直接入力、ブックマークからのアクセスの際には値がない
REMOTE_ADDRリモートホストのIPアドレス情報
REMOTE_HOSTリモートホストのドメイン名
REMOTE_IDENTリモートホストのユーザ名
REMOTE_USERユーザの認証名
ウェブサーバとリモートホストがユーザ認証プロトコルを実行しているときだけ値がある
#環境変数の列挙

#!/usr/local/perl
print "Content-type: text/html\n\n";
print "<html><head><title></title></head><body>\n";
foreach my $key( keys %ENV ){
    print "$key: $ENV{$key}<br>\n";
}
print "</body></html>", "\n"; 
#ブラウザ判別

#!/usr/local/perl
print "Content-type: text/html\n\n";
my $agent = $ENV{'HTTP_USER_AGENT'};
if ( $agent =~ /^Mozilla/ ){
    if ( $agent =~ /^Mozilla\/[0-9\.]+\s\(compatible\; MSIE/ ){
        print "IE\n";
    } else {
        print "NN\n";
    }
} else {
        print "OTHER\n";
}
#ドメイン判別

#!/usr/local/perl
print "Content-type: text/html\n\n";
my $host_address = 'sevenkey\.ddo\.jp';

if ( $ENV{'REMOTE_HOST'} =~ /^\.$host_address$/ ){
   print "Success in login\n";
} else {
   print "Failure of login\n";
}

◇ コマンド引数

コマンドラインからの引数を得るために、次の変数が使用できる

@ARGV          # 引数の配列
$#ARGV         # 配列の個数−1
$ARGV[0]       # 最初の引数
$ARGV[$#ARGV]  # 最後の引数

◇ シグナル

プログラムに送信される非同期のメッセージ。例えば、強制終了を明示された時はSIGTERMシグナルが、プロセス間の通信が切断された時はSIGPIPEメッセージが、設定しておいた時刻になったらSIGALRMシグナルが、プログラムに対して送信される。

$SIG{'TERM'} = "sigexit";

と宣言することにより、そのプログラムに SIGTERMシグナルが送信された時に、&sigexit()関数が実行されるようになる

◇ 特殊変数

$.入力時のレコード区切り文字。通常は改行
$,出力時の項目区切り文字。print @exp; の時に有効
$"出力時の項目区切り文字。print "@exp"; の時に有効
$\出力時の行末文字。print "$exp"; の後ろに付加される
$#出力時の数値形式。通常は"%.20g"。
$%出力時の現在のページ番号
$=出力時の現在のライン数
$-出力時の残り行数
$~出力時のフォーマット名
$^出力時のヘッダフォーマット名
$|0以外が代入されると出力をバッファリングしなくなる
$$プロセスID
$?最後に実行されたコマンドのステータス
$&パターンマッチにマッチした部分文字列
$`パターンマッチにマッチした部分の前側の文字列
$'パターンマッチにマッチした部分の後側の文字列
$+パターンマッチの最後の()に対応する文字列
$0perlスクリプトのコマンド名
$1パターンマッチの際の1番目の()に対応する文字列
$[配列の最初の添え字
$]perlのバージョン情報
$;高次元連想配列の添え字の区切り文字
$!エラー番号、もしくはエラー文字列
$@直前のevalコマンドのエラーメッセージ
$<このプロセスの実ユーザーID
$>このプロセスの実効ユーザーID
$(このプロセスの実グループID
$)このプロセスの実効グループID
$^Dデバッグフラグの値
$^Fシステムファイルディスクリプタの最大値
$^I-iオプションで指定した拡張子の名前
$^Pデバッガが使用する内部フラグ
$^Tスクリプトを実行した時刻
$^W警告スイッチの現在値
$^Xperl自身の起動時の名前
@_ サブルーチンへの引数
@INCperlライブラリ検索ディレクトリ
%INC読み込まれたライブラリファイルの配列
_LINE_スクリプト中の現在の行数
_FILE_スクリプトのファイル名

◇ ファイル検査

ファイルが書き込み可能かどうか等を調べる

if (-w "samp.txt") { }

-r読み込み可能チェック
-w書き込み可能チェック
-x実行可能チェック
-o自分のものチェック
-R実uid/gidで読み込み可能チェック
-W実uid/gidで書き込み可能チェック
-X実uid/gidで実行可能チェック
-O実uidのものチェック
-e存在チェック
-zサイズチェック
-sサイズチェック(ファイルサイズを返す)
-f通常ファイルチェック
-dディレクトリチェック
-lシンボリックリンクチェック
-p名前付きパイプチェック
-Sソケットチェック
-bブロック型スペシャルファイルチェック
-cキャラクタ型スペシャルファイルチェック
-usetuidビットチェック
-gsetgifビットチェック
-kstickyビットチェック
-tファイルハンドルが tty としてオープンされていれば
-Tファイルがテキストファイルであれば
-Bファイルがバイナリファイルであれば
-Mperl起動時における、ファイルの更新時刻からの日数
-Aperl起動時における、ファイルの参照時刻からの日数
-Cperl起動時における、ファイルの作成時刻からの日数