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文書で半角空白<>など特殊な文字は下記で記述。
   &nbsp;  (半角空白)
   &lt;   <
   &gt;   >
   &amp;   &
   &quot;  "(これは単に"と書いても良いが、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/</&lt;/g; # 変数$xに文字"<"があるとき、これを文字列"&lt;"に置換。
  これらの場合は、/は必ず/である必要はないが、習慣的に/を使う場合が多い。
  また最初の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メモ:終わり)