指定したディレクトリの特定の名前のファイルを削除するスクリプトを作ってみました。
削除するファイル名は「***(1).mp3」のようなmp3ファイルで、( )内の数字は1桁の数値が入っています。
#! /bin/perl -w use strict; my $dirname = 'C:\Documents and Settings\work'; opendir(DIR, $dirname) or die "$dirname: $!"; while (my $dir = readdir(DIR)) { next unless ($dir =~ /\(\d\)\.mp3$/); my $filename = $dirname.'\\'.$dir; print '削除ファイル ===== ', "$filename\n"; unlink($filename); } closedir(DIR);
opendirでディレクトリをディレクトリハンドル"DIR"に関連付けて、readdirで読み込みます。
正規表現のパターンマッチでファイルを選別して、削除しています。
readdirで読み込むのがディレクトリエントリというのが理解できなくて、unlink($dir);として、動作しなくて少し悩みました。unlink($dir);だとカレントディレクトリの$dirというファイルが削除されるんですね。
my $filename = $dirname.'\\'.$dir;のようにして、きちんとファイルを指定する必要がありました。
はてなスターありがとうございます。Uchimataさん。
ファイルの入出力を学習しました。
#! /bin/perl -w use strict; my $filename = 'data.txt'; open (FILE, $filename) or die "$filename: $!"; for (my $i=0; $i<3; $i++) { my $line = <FILE>; print $line; } close (FILE);
複数のファイルを処理できれば、簡易プレビューできそうです。バイナリファイルだった場合に、最初の数行で中身の判別とかはできるのか、わからないですけど。
はてなスターありがとうございます。tokumuraさん。
practice |
時期的にも合うのでこのクイズを解いてみました。
このようなクリスマスツリーを書くプログラムを作るという課題です。
*
*!*
*!*!*
*!*%*!*
*!*%/%*!*
*!*%/*/%*!*
*
*!*
*!*!*
*!*%*!*
*!*%/%*!*
*!*%/+/%*!*
*!*%/+-+/%*!*
*!*%/+-!-+/%*!*
*!*%/+-!.!-+/%*!*
*!*%/+-!.*.!-+/%*!*
*!*%/+-!.***.!-+/%*!*
*!*%/+-!.**%**.!-+/%*!*
*!*%/+-!.**%/%**.!-+/%*!*
*!*%/+-!.**%/*/%**.!-+/%*!*
*!*%/+-!.**%/*+*/%**.!-+/%*!*
最初に考えたのは
#! /bin/perl -w use strict; my @takasa = ('6', '16',); my @parts = qw(* ! * % / * + - ! . * * % / * +); foreach my $h(@takasa){ for (my $i = 1; $i <= $h; $i++){ print ' ' x ($h - $i); for (my $m = 0; $m < $i; $m++){ print $parts[$m]; } for (my $n = ($i - 2); $n >= 0; $n--){ print $parts[$n]; } print "\n"; } print "\n"; }
forループで右側+中央と左側をprintするのを高さ分だけ繰りかえす2重ループ
次にヒントありでできたのが
#! /bin/perl -w use strict; my @tree = ('*!*%/*', '*!*%/+-!.**%/*+'); #葉 foreach (@tree) { my @leaf = split(//, $_); my @branch = (); while (@leaf) { my $center = shift(@leaf); print " " x @leaf, @branch, $center, reverse(@branch), "\n"; push (@branch, $center); } }
すっきりできました。
解答は結城浩の『Perlクイズ』 [まぐまぐ!]にありますが、2文で出来るとはびっくりです。まだ、学んでいない関数を使ってるとはいえ驚きました。
スクリプトファイルの1行目に書く #! の付く行をシェバング行という。
もともとはUNIXの習慣で、ファイルの中身をシェバング行のコマンドに渡す。
#! /bin/perl
これだと、2行目以降がperlコマンドに渡される。
WindowsのActivePerlの場合は、意味がないかというと、そんなことはなくて、-d でデバッガーを実行したり、-w で警告をオンにしたりできる。
Perlのスクリプトであることがわかりやすいのでつけたほうがよい。
あまり意味はないけれど、-c や -v などもここに記述すると効果がある。
"-c" は文法チェックしてくれる。けれど、シェバング行に記述するよりもコマンドでオプションで渡したほうがいいですね。
"-v" はバージョンを表示するだけで中身のスクリプトは実行されないので意味なしでした。
スクリプトの書き出しはこれのほうがよさそう。
#! /bin/perl -w use strict; use warnings;
use warnings; は1行目に "-w" を記述しておけばいらないような気もする。
はてなスターありがとうございます。tokumuraさん。
practice |
練習問題として、任意の年($year)がうるう年かどうかチェックするというのを考えてみました。
うるう年の判定条件は、
4で割り切れる年はうるう年
しかし、100で割り切れる年はうるう年ではない
しかし、400で割り切れる年はうるう年
最初に書いたスクリプト
use strict; use warnings; my $year = "2008"; #ここに調べたい年を入れる if ($year % 4 != 0) { print "$year年はうるう年ではない。\n"; } elsif ($year % 100 == 0) { if ($year % 400 == 0) { print "$year年はうるう年。\n"; } else { print "$year年はうるう年ではない。\n"; } } else { print "$year年はうるう年。\n"; }
わかりにくいです。条件が複数ある場合は、一番厳しい条件から書いたほうが良いとのことで、この場合は、400で割り切れるかどうかを最初に判定すると、
use strict; use warnings; my $year = "2008"; #ここに調べたい年を入れる if ($year % 400 == 0) { print "$year年はうるう年。\n"; } elsif ($year % 100 == 0) { print "$year年はうるう年ではない。\n"; } elsif ($year % 4 == 0) { print "$year年はうるう年。\n"; } else { print "$year年はうるう年ではない。\n"; }
こちらのほうがわかりやすくなりました。
ネットでみつけた、シンプルな解答
use strict; use warnings; my $year = "2008"; #ここに調べたい年を入れる if ($year % 400 == 0 or ($year % 100 != 0 and $year % 4 == 0)) { print "$year年はうるう年。\n"; } else { print "$year年はうるう年ではない。\n"; }
わかりやすいです。
追記
トラックバックいただきました。
「うるう年かどうかチェックする」をif~elseを使わずに書いてみた - ishiducaの日記 - Hatena::Group::Perl
うるう年 - negipoのPerl日記 - Hatena::Group::Perl
ありがとうございます。
この本を読んで勉強中です。わかりやすくてよいと思います。章の終わりに練習問題があって復習できて、いいですね。
初級者向けの練習問題をもう少しやりたいと思うのですがなかなかみつからないものです。自分で問題を考えられるようになりたいです。
はてなスターありがとうございます。tokumuraさん。