「初めての Perl」勉強7日目

ファイルやディレクトリの操作って苦手なんだと実感した13章

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

練習問題1

rm と同じ働きをするプログラムを書いてください。このプログラムは、コマンドラインに指定した全てのファイルを削除します。

#!/usr/local/bin/perl -w

chomp (my @in = <STDIN>);

unlink "@in";

foreach my $file (@in) {
    print "delete $file\n";
}
練習問題2

mv と同じ働きをするプログラムを書いてください。このプログラムは、1番目のコマンドライン引数で指定したファイルを、2番目のコマンドライン引数で指定した名前にリネームします。2番目の引数にはディレクトリも指定できるようにしてください。その場合、新しいディレクトリの中で、リネームする前と同じベース名をもつようにします。

分かりません><
解答より。

#!/usr/local/bin/perl -w

use File::Basename;
use File::Spec;

my($source, $dest) = @ARGV;

if (-d $dest) {
    my $basename = basename $source;
    $dest = File::Spec->catfile($dest, $basename);
}

rename $source, $dest
    or die "Can't rename '$source' to '$dest': $!\n";
練習問題3

あなたが使っているオペレーティングシステムがハードリンクをサポートしているなら、ln と同じ働きをするプログラムを書いてください。このプログラムは、1番目のコマンドライン引数に対して、2番目の引数で指定した名前をもったハードリンクを作成します。あなたのシステムがハードリンクをサポートしていなかったら、サポートされていた場合に行うはずの操作を示すメッセージを表示するようにしてください。

#!/usr/local/bin/perl -w

use File::Basename;
use File::Spec;

my($source, $dest) = @ARGV;

if (-d $dest) {
    my $basename = basename $source;
    $dest = File::Spec->catfile($dest, $basename);
}

link $source, $dest
    or die "Can't link '$source' to '$dest': $!\n";

単純に考えればこれでいいはず。

練習問題4

あなたが使っていロペレーティングシステムがシンボリックリンクをサポートしているなら、問題3のプログラムを改造して、引数の前に -s スイッチを指定した場合に、ハードリンクの代わりにシンボリックリンクを作成するようにしてください。

-s スイッチの部分が分からなかった
解答を見る

#!/usr/local/bin/perl -w

use File::Basename;
use File::Spec;

my $symlink = $ARGV[0] eq '-s';
shift @ARGV if $symlink;

my ($source, $dest) = @ARGV;

if (-d $dest) {
    my $basename = basename $source;
    $dest = File::Spec->catfile($dest, $basename);
}

if ($symlink) {
    symlink $source, $dest
        or die "Can't make soft link from '$source' to '$dest': $!\n";
}
else {
    link $source, $dest
        or die "Can't make soft link from '$source' to '$dest': $!\n";
}

これはまた無理矢理感がある気がするが。。。

練習問題5

あなたが使っているオペレーティングシステムシンボリックリンクをサポートしているなら、カレントディレクトリに存在する全てのシンボリックリンクを探し出して、その値を表示するプログラムを書いてください。

シンボリックリンクのみを取り出すのか。フックが分からん。
よって解答を見た

#!/usr/local/bin/perl -w

foreach (<.* *>) {
    my $dest = readlink $_;
    print "$_ -> $dest\n" if definde $dest;
}

第十四章 プロセス管理

練習問題1

あるディレクトリ(例えばシステムのルートディレクトリ)に移動してから、ls -l コマンドを実行して、そのディレクトリに対する詳細形式のディレクトリリストを表示するプログラムを書いてください。

#!/usr/local/bin/perl -w

system 'ls -l /';
練習問題2

問題1のプログラムを改造して、コマンドの出力をカレントディレクトリの ls.out というファイルに書き出すようにしてください。また、エラー出力は、ls.err と言うファイルに出力してください。

わかんない><

#!/usr/local/bin/perl -w

open STDOUT, ">ls.out" or dir "Can't write to ls.out: $!";
open STDERR, ">ls.err" or dir "Can't write to ls.err: $!";
chdir "/" or dir "Can't chdir to root dir: $!";
exec "ls", "-l" or dir "Can't exec ls: $!";
練習問題3

date コマンドのスツ力を解析して、今日が何曜日かを調べるプログラムを書いてください。もしウィークデーなら get to work、そうでなければ go play と表示するようにしてください。

うまくいかないもんだな。一応書いたもの。

#!/usr/local/bin/perl -w

my @date = `date`;
my $wk = shift(@date);
my @week = qw / 日 土 /;

foreach $w (@week) {
    if ($wk eq $w) {
        print "go play $w\n";
    }
    else {
        print "get to work $w\n";
    }
}

これだと2回出る。どーしたものやら。と言うわけで解答。

#!/usr/local/bin/perl -w

if (`date` =~ /^S/) {
    print "go play!\n";
}
else {
    print "get to work!\n";
}

ASCII 圏の連中はこれだからwww
Sundey と Saturday は頭文字が S だからって理由でこんなの書くしw
日本じゃ漢字じゃヴォケwww

第十五章 文字列処理とソート

ここで出てくるソートは使ったことがある

練習問題1

数値のリストを読み込んで、それを数値としてソートした上で、右寄せで表示するプログラムを書いてください。(数値リスト:17 1000 04 1.50 3.14159 -10 1.5 4 2001 90210 666)

#!/usr/local/bin/perl -w

my @number = qw / 17 1000 04 1.50 3.14159 -10 1.5 4 2001 90210 666 /;
my @sort = sort { $a <=> $b } @number;

foreach $num (@sort) {
    printf "%10s\n", $num;
}

右寄せってところが気になったが、たぶんこれでいいはず。

練習問題2


次に示したハッシュのデータを、姓のアルファベット順でソートして表示するプログラムを書いてください。姓が同じ場合には、名によってソートします。同じ姓を持つ人たちは、まとまって表示されるはずです。名前は大文字と小文字の使い分けを変えずに、ここに示したままで表示してください。

my %lastname = qw { fred flintstone Wilma Flintstone Barney Rubble betty rubble Bamm-Bamm Rubble PEBBLES FLINTSTONE };

面倒なハッシュ作りやがって。。。

#!/usr/local/bin/perl -w

my %lastname = qw { fred flintstone Wilma Flintstone Barney Rubble betty rubble Bamm-Bamm Rubble PEBBLES FLINTSTONE };
my @keys = sort by_sort keys %lastname;

sub by_sort {
    $lastname{$b} cmp $lastname{$a}
        or
    $b cmp $a
}

foreach $name (@keys) {
    print "$name $lastname{$name}\n";
}
練習問題3

ユーザから与えられた文字列の中から、与えられた部分文字列が現れる場所を全て探し出して、その位置を表示するプログラムを書いてください。このプログラムに対して、文字列に "This is a test."、部分文字列に "is" を与えると、位置2と5が表示されるはずです。

ユーザが入力する順序は文字列>部分文字列と仮定。

#!/usr/local/bin/perl -w

chomp(my @int = <STDIN>);

my $text = shift @int;

while (@int) {
    my $x = index($text, $_);
    print "$x\n";
}

でまあ書いてみたがダメだったので解答を見た。

#!/usr/local/bin/perl -w

chomp(my $string = <STDIN>);
chomp(my $sub = <STDIN>);

my @places;

for (my $pos = -1; ; ) {
    $pos = index($string, $sub, $pos +1 );
    last if $pos == -1;
    push @places, $pos;
}

print "Locations of '$sub' in '$string' were: @places\n";

こんなの知るかよ。。。

第十六章 単純なデータベース

DBM とかよさそうだなぁ、と思ったけど練習問題やって激しいと思った。

練習問題1

perlfunc.pod ファイルを読んで、その中から =item 行に置かれている識別子名を探し出すプログラムを書いてください。このプログラムは、各識別子が登場する最初の行番号を記録したデータベースを作成します。

ま た こ れ か
さっぱりだから解答見た

#!/usr/local/bin/perl -w

open PF, '/usr/local/lib/perl5/5.8.8/pods/perlfunc.pod' or die "Cannot open perlfunc.pod: $!";
dbmopen my %DB, "pf_data", 0644 or die "Cannot create dbm file: $!";

%DB = ();

while (<PF>) {
    if (/^=item\s+([a-z_]\w*)/i) {
        $DB{$1} = $DB{$1} || $.;
    }
}

print "Done!\n";

分からんよ。。

練習問題2

コマンドラインから Perl 関数の名前を1個受け取って、perlfunc.pod ファイルの中で、その関数が最初に現れる =item 行の行番号を表示するプログラムを書いてください。

なんでこうも難しいんだろ。

#!/usr/local/bin/perl -w

dbmopen my %DB, "pf_data", undef or die "Cannot create dbm file: $!";
my $line = $DB{$ARGV[0]} || "not fount";

print "$ARGV[0]: $line\n";

ARGV[0] って発想がそもそもオレにはない。

練習問題3

問題2のプログラムを改造して、データベースから関数を見つけたら、あなたのお気に入りのページャプログラムを起動して、perlfunc.pod ファイルのその行を見られるようにしてください。

ページャプログラムなんて出てきたっけ?

#!/usr/local/bin/perl -w

dbmopen my %DB, "pf_data", undef or die "Cannot create dbm file: $!";

if (my $line = $DB{$ARGV[0]}) {
    exec 'less', "+$line", '/usr/local/lib/perl5/5.8.8/pods/perlfunc.pod'
        or die "Cannot exec pager: $!";
}
else {
    die "Entry unknow: '$ARGV[0]'.\n";
}

UNIX のコマンドか。