Perl によるプログラム作成メモ
2009/03/03 © 葉流奈津
ご注意:これはPerl を一通り理解した人が、その内容を再確認するための〈覚え〉のようなものです。
一般
・#以降は行末までコメント。
・代入や入出力など単ステートメントの末尾には必ず;が必要。
・Perlにはデータ型の宣言がない。
・変数名は $、@、% のいずれかで始まり、2文字目は英字または _ であるべき。
3文字目以降は英数字または _ が可能。
変数
・$で始まる変数はスカラー変数または配列要素。
$x = 5; $a[2] = "ABC"; $b{'名前'} = "山田"; など
・また$_は特殊な変数名。(あるケースで変数名を省略した場合の既定の変数)
配列
・@ で始まる変数は配列で、配列は宣言不要。配列の添え字は普通は0から。
@a = ("abcd", "efg", "12345"); このとき $a[0]の値は"abcd"
・次のような書き方もできる。
@a[3..4] = ("hijk", "lnm");
(注)$aと書いた変数と、@aと書いた変数とは全く別物。
・配列 @aの要素数は変数 $#aで分かる。$#aの内容は、要素数-1。
・配列要素全てを操作する場合の構文。
foreach $xxx (@a) { # 配列要素0から順に$xxxに代入される。
print "$xxx\n";
}
連想配列
・通常の配列(前掲)のほかに連想配列がある。
・連想配列とは下記例のようなもの。
$meibo1{'氏名'} = "○山△子";
$meibo1{'住所'} = "東京都○○区...";
・連想配列全体を定義する場合は、次のように書く。
%meibo1 = ("氏名", "○山△子", "住所", "東京都○○区...");
・連想配列の要素全てを操作する場合の構文。
while (($name, $value) = each(%meibo1)) {
print "$name = $value\n";
}
文字列
・文字列は'または"でくくる。
(両者は多少解釈が異なり、"の場合は中に変数を入れられる。)
$a = '山田'; print "名前は$a。"; print '名前は$a。'; とすると
名前は山田。名前は$a。 とプリントされる。
・"日本語文字列"の場合は文字化けする文字もある。
例えば"表"などがこれに該当する。
このとき"表\示"などと該当文字の後に\を書いておけば良い。
よく使われる文字で、文字化けするものは右記。(申 十 ソ 能 予 貼 表 圭 免)
・Perl自体のことではないが、HTML文書で半角空白<>など特殊な文字は下記で記述。
(半角空白)
< <
> >
& &
" "(これは単に"と書いても良いが、Perl文中では\"と書くべき。)
単項演算子
インクレメント($a++;)、デクレメント($a--;)など。
ほかに、- マイナス、~ bit否定、! 論理否定。
二項演算子
・数値演算は +、-、*、/、**(べき乗)、%(剰余) など
・文字列結合
$a = $a . "abc"; # これは $a .= "abc"; と書いてもよい
・ビット演算子
$a | $b # bit OR
$a & $b # bit AND
$a ^ $b # bit XOR(排他的論理和)
~$a # bit NOT
$a >> 2 # bit SHIFT 2bit( << は逆方向)
文字列比較
if ($xx eq "ABC") # 等しければ
if ($xx ne "ABC") # 等しくなければ
if ($xx =~ /ABC/) # 文字列ABCが含まれていれば
if ($xx =~ /^ABC/) # 文字列ABCで始まっていれば
if ($xx !~ /ABC/) # 文字列ABCを含んでいなければ
if ($xx =~ /[0-9]+/) # 正規表現(別途説明)にマッチしていれば
正規表現
abc 文字列abc
a+ 1個以上のa
a* 0個または1個以上のa
. 任意1文字
? 0個の文字または任意1文字
^abc abcで始まる
abc$ abcで終わる
[abc] a、b、cのいずれか
[a-z0-9] aからz、または0から9
[^ab] a、b以外
[^a-z] aからz以外
a|b|c aまたはbまたはc
\s 空白文字 (\何々は他に各種あるが略)
メタ文字(+ * ? . ( ) [ ] { } | \ @)は前に\をつければ指定可。
(正規表現)や\1、\2、\3という書き方もある。\1は1番目の(正規表現)ということ。
マッチした場合は$1、$2、$3、$+、$&という書き方もする。
$1 は1番目の(正規表現)にマッチした文字列。
$+ は(正規表現)の最後にマッチした文字列。
$& は()付きでない正規表現の場合に、マッチした文字列。
数値比較
==、!=、<、>、<=、>=
if ($a == 1 || $a == 2) # OR 関係
if ($a == 0 && $b == 0) # AND関係
真と偽
・0, "0", "" は偽と見なされる。それ以外は全て真と見なされる。
文字列の分解
@a = split(/&/, $sss); # 文字列$sssを区切り文字&で分解して配列@aに格納。
配列@aには$a[0],$a[1],....と順に埋められてゆく。
(splitは組み込み関数で、他の関数は別項参照)
文字列の置換
$x =~ s/</</g; # 変数$xに文字"<"があるとき、これを文字列"<"に置換。
これらの場合は、/は必ず/である必要はないが、習慣的に/を使う場合が多い。
また最初のsと最後のgは、それぞれに意味がある。
最初のsは置換を表す。
最後のgはオプションで、全てのパターンについてという意味。
gがないと1回だけ置換。
オプションにはいろいろあるが、よく使うのはgとeで、eについては説明を略す。
制御構文
if ($a == 1) {
$b = "ichi";
} elsif ($a == 2) {
$b = "ni";
} else {
$b = "hoka";
}
while ($buf = <IN>) {print "$buf\n";}
for ($i = 1; $i <= 10; $i++) {print "Counter = $i\n";}
入出力
open (IN, "datafile.txt"); # 入力ファイルのopen
open (OUT, "> datacopy.txt"); # 出力ファイルのopen
while ($bf = <IN>) {print <OUT> $bf;}
close (OUT)
close (IN)
追加出力の場合は下記のように。
open (OUT, ">> datacopy.txt"); # 追加出力ファイルのopen
(注)IN、OUTなどの文字は任意である。大文字は慣例による。
ファイル検査
$siz = -s "datafile.txt"; # ファイル長さ
if (-f "datafile.txt") {...;} # ファイルが有れば
if (-d "datafldr") {...;} # ディレクトリが有れば
プログラムの構成
通常は1ソースファイルに1つのメインと複数のsubroutineを記述する。
普通はソースプログラムの先頭から順に実行される。
exit; 文が現れるか、またはソースの最後まで行くと実行は終了する。
サブルーチンは次のような書き方。
sub outdoc {
...(ステートメント)...; # 呼び出し側で引数を指定した場合は$_[0]で参照。
}
サブルーチン呼び出し側は下記のように。
&outdoc($arg1, $arg2); # 引数ある場合はこのように書く。
PerlをCGIとして実行
・HTMLからCGIプログラムを実行させる場合は、HTMLで次のように記述する。
<A HREF="cgi-bin/msgboard.cgi?kanri+25">CGI実行</A>
つまり、通常の参照用タグを使い、CGIプログラムを起動させる。
? 以降はCGIに渡す引数で、引数が2個以上の場合は + で区切って記述する。
CGIプログラム側では $ARGV[0] で引数を参照する(変数名は決まっている)。
上の例では"25"は$ARGV[1]に格納されている。
・ブラウザ側で入力されたテキストなどを取込む場合は、HTMLで<FORM>タグを使う。
(例)
<FORM METHOD=POST ACTION="msgboard.cgi">
お名前:<INPUT TYPE=text NAME="NAME" SIZE=54 VALUE=""><BR>
URL:<INPUT TYPE=text NAME="URL" SIZE=54 VALUE=""><BR>
<INPUT TYPE=submit VALUE=" 送信 "><BR>
</FORM>
よく使う組み込み関数
int(fff) :fffの整数部を返す。つまり切り捨て。
sqrt(fff):平方根。その他sin(radian)、cos(radian)、atan2(bunshi, bunbo)など。
mkdir(filename, mode)
ディレクトリを作成する。modeにはディレクトリのパーミッション(0755)を指定。
rmdir(filename)
ディレクトリを削除する。
pack(template, list)
バイナリデータを生成する。
templateでlistがどんな形式のデータなのかを指定する。
後ろに数値を付けるとその個数分、アスタリスク(*)をつけるとlistの最後まで、
バイナリデータに変換する。
a ASCII string(ヌル文字が補完される)
A ASCII string(スペースが補完される)
c 符号付き1バイト数値(-128 〜 127)
C 符号無し1バイト数値(0〜255) ←CGIでは、普通これを使う
templateのキーワードにはその他多数あるが、記述を省略する。
unpack(template, expr)
バイナリデータを解釈する。templateはpackのものと同様。
unpack("C", "A") # AのASCIIコード0x41を返す
length(expr)
exprで与えられる文字列の長さを返す。
substr(expr, offset, length)
文字列の一部を取り出す。exprで与えられる文字列のうちoffset文字からlength
文字分を返す。最初の文字は通常は0文字目。
offsetが負の値の時は、文字列の最後から-offset文字目(最後の文字は1文字目)
から後ろ方向にlength文字分を返す。
lengthを省略すると残りの全てを返す。
crypt(passwd, salt)
パスワードを暗号化する。
暗号化したパスワードから元のパスワードを解読することは(多少)困難だが、
元のパスワードをチェックすることは容易にできる。
解読を困難にするために、saltにはドット(.)、スラッシュ(/)を含む2文字の
英数文字をランダムに指定する。
この2文字は暗号化されたパスワードの最初の2文字となる。
# パスワード($epasswd)を暗号化する
$passwd = "himitsu";
$xx = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./";
$salt = substr($xx, int(rand(64)), 1);
$salt .= substr($xx, int(rand(64)), 1);
$epasswd = crypt($passwd, $salt); # 通常これをファイルに保存する
# パスワードで暗号化したパスワードをチェックする
$salt = substr($epasswd, 0, 2);
if ($epasswd eq crypt($passwd, $salt)) {
print "Match!!\n";
}
(Perlメモ:終わり)