初めてのPerlを読み返す 10−13章 制御構造・ファイルとディレクトリ

初めてのPerl
初めてのPerl
posted with amazlet at 09.04.05
ランダル・L. シュワルツ トム フェニックス
オライリージャパン
売り上げランキング: 34126


この記事のスタンスはこちら


10章 さまざまな制御構造*1

  • ループ制御
    • last演算子 ループを終了させる(Cのbreak)
    • next演算子 現在行っている繰り返しを終了させる(Cのcontinue)
    • redo演算子 現在行っている繰り返しをもう一度行う(Cには同じ演算子は無い)
  • ラベル付きブロックを使うと、ラベル指定でループ制御演算子を使用できる。
LINE: while(<>){
  foreach(split){
    last LINE if 条件; # LINEループから抜ける
  }
}
  • 論理演算子は「左側から評価され、偽であれば次の評価を行う」という動作をする。
    以下は、これを利用したデフォルト値の設定方法。
# $aaaがundefの場合、「default value」が設定される。
my $aaa = $aaa || 'default value';
# ちなみに、上記のように代入元と代入先が同じ場合は以下も同じ動作になる(はず…)
$aaa ||= 'default value';
  • 論理演算子「&&」「||」と同じような動作をする演算子としてワード形式の「and」「or」がある。ワード形式のほうが優先順位が低い
# 以下は全て同じ意味。
# もちろん、ifを使って書いた方が良い
if($a < $b) { $a = $b; }
($a < $b) && ($a = $b);
$a < $b and $a = $b;

11章 ファイルハンドルとファイルテスト

  • Perl自身が使用する特別なファイルハンドル
    • STDIN
    • STDOUT
    • STDERR
    • DATA
    • ARGV
    • ARGVOUT
  • 「die」は致命的エラーを発生させ、プログラムを終了する。
    「warn」は警告メッセージを出力し、プログラムを継続する。
  • ファイルハンドルのオープン/クローズ/使用例
open MYFILE, "file.txt";   # 読み込みでオープン
open MYFILE, "<file.txt";  # 読み込みでオープン
open MYFILE, ">file.txt";  # 新規書き込みでオープン
open MYFILE, ">>file.txt"; # 追記書き込みでオープン

print MYFILE "Hello\n"; # ファイルハンドルを使う

close MYFILE; # ファイルハンドルをクローズ

# ファイルチェックをしつつオープン
# 特殊変数「$!」はシステムからのエラーメッセージが設定される
unless (open MYFILE , ">>file.txt") {
  die "Cannot create file.txt: $!";
}
# もう一つの方法
open MYFILE , ">>file.txt" or die "Cannot create file.txt: $!";
select BEDROCK
print "aaa\n";  # BEDROCKに出力される
print "bbb\n";  # BEDROCKに出力される
  • 特殊変数「$|」に「1」をセットすると、出力のバッファリングをしなくなる。
  • ファイルテストの一覧はこちらを参照するとよろし。
  • stat関数で、Unixシステムコールによって得られるほぼすべての値を取得できる。
my (
 $dev,     # ファイルシステムのデバイス番号
 $ino,     # iノード番号
 $mode,    # ファイルのモード
 $nlink,   # ファイルへのハードリンク数
 $uid,     # ファイル所有者のユーザID
 $gid,     # ファイル所有者のグループID
 $rdev,    # 特殊ファイルのデバイス識別子
 $size,    # ファイルのサイズ(バイト単位)
 $atime,   # 最終アクセス時刻
 $mtime,   # 最終変更時刻
 $ctime,   # 最終iノード変更時刻
 $blksize, # 標準のファイルシステム入出力時の標準ブロックサイズ
 $blocks   # ファイルに割り当てられてりるブロック数
) = stat($file); 
  • localtime関数でタイムスタンプを変換する
my (
 $sec,  # 秒
 $min,  # 分
 $hour, # 時
 $mday, # 日
 $mon,  # 月(0-11)
 $year, # 年(1900を引いた年数)
 $wday, # 曜日(0-6)(0は日曜日)
 $yday, # 元旦からの日数
 $isdst # サマータイム期間かどうかのフラグ
) = localtime $timestamp;

12章 ディレクトリ操作

# @pm_filesにはファイル名をアルファベット順に並べたものがセットされる
my @pm_files = glob "*.pm";
# 同じこと
my @pm_files = <*.pm>;
my $dir = "/etc";
opendir DH , $dir or die "Cannot open $dir: $!";
# readdir で得られる $file はフルパスではない事に注意!(ファイル名のみ格納される)
foreach my $file (readdir DH){
  print "$dir is $file \n";
}
closedir DH;
  • 再帰的なディレクトリ処理を使用する場合は「File::Find」というモジュールを使うといいよ。

13章 ファイルとディレクトリの取扱い

  • ファイル操作
    • unlink演算子でファイルを削除する(unixのrmと同様)。戻り値は削除したファイルの個数
    • rename演算子でファイルの名前を変更する(unixのmvと同様)
  • Unixのファイルとディレクトリモデル(iノードとリンク数の操作)
    • link演算子で新しいリンク(ハードリンク)を作成。
    • symlink演算子シンボリックリンク(ソフトリンク)を作成。
    • readlink演算子でシンボリックが差している場所を取得。
    • なぜファイル削除が「rm」ではなく「unlink」なのかわかったかな?
  • ディレクトリ操作
  • chmod演算子パーミッションを変更できる。
  • chown演算子でファイルオーナーを変更できる。
    • getpwnam関数でユーザ名をユーザIDに変換。
    • getgrnam関数でグループ名をグループIDに変換。
  • utime関数でファイルのタイムスタンプを設定出来る。
# カレントディレクトリの全ファイルを「現在アクセスされた」「1日前に更新された」ように見せかける。
my $now = time;
my $ago = $now - 24 * 60 * 60 ;
utime $now, $ago, glob "*";
  • 「File::Basename」モジュールで、ファイル名からベース名(ディレクトリのフルパス)を取得できる。WindowsUnixも区別なく使用できるよ!
  • 「File::Spec」モジュールで「ベース名+ファイル名」のような文字列を取得できる。もちろんWindowsUnixも(rya


今回は結構端折りました。
Linuxを触っているので既知の事項も多いですが、
Perl独特の違いもあるため、あえて記述した部分もあります。

*1:以下引用をいくつか含みます