Perl初心者の部屋
PageID:Perl-Newbie Programing
Last update:00.04.07
Perl初心者のFAQのページ [初級プログラミング編]
Q1.)
Windowsでxxxxxx.pl?の起動中に他のプログラム(BAT,Excel,VB,etc...)
を起動させたいのですが、方法が解りません!
Q2.)
OSコマンド等をPerlから使用するのに、system関数だとうまくいくのですが、
バッククォート``だと出力が出てきません。どうしてでしょうか?
Q3.)
perlで有効桁数小数点以下第2位とかの設定はできるのでしょうか
Q4.)
下記のようにして、0から20までのランダムな数をえようとしましたが、
どうしても出力してくれません!
$deta=int(rand(20));
Q5.)
小数点処理(小数点以下の切り捨て、四捨五入)がよくわかりません。
Q6.)
実行中のPerlスクリプトがあるディレクトリを知るにはどうすればよいでしょうか。
Q7.)
階層になっているフォルダがあるのですが、再帰的にすべてのフォルダにあるファイルを取り出すにはどうすればよいでしょうか。
Q8.)
プロンプトからのキー入力を自動化させたいのですが、どうすればよいでしょうか。
Q9.)
CSV(Comma-Separated Value:コンマ区切りデータ)から値を取り出したいのですが、どうすればよいでしょうか。
Q10.)
ファイルをコピーしたり移動したいのですが、どうすればよいでしょうか。
Q11.)
ファイルの中身が同じものかどうか比較したいのですが、どうすればよいでしょうか。
Q12.)
"xxx.txt"のようなファイル名からxxxの部分だけ抜き出して表示したいのですが、どうすればよいでしょうか。
Q13.)
多階層のディレクトリを生成したいのですが、何か簡単な方法はないでしょうか。
Q14.)
2 進数を16進数に変換したいのですが、どうすればいいのでしょうか
。
Q1.) Windowsでxxxxxx.pl?の起動中に他のプログラム(BAT,Excel,VB,etc...)
を起動させたいのですが、方法が解りません!
A1.)
使用しているのはperl5 for Win32だと想定します。
外部コマンドの起動について、基本的には
1.system()
2.exec()
3.バッククォート
の3通りあります。
コマンドラインから下記でそれぞれ確認できます。
perl -e "system 'echo \"hellow\"';"
perl -e "exec 'echo \"hellow\"';"
perl -e "print `echo \"hellow\"`;"
それぞれの違いはperlfuncやラマ本等を参照してください。
このほか、Perl と C ライブラリ 間の拡張インタフェースを作るためのXSという言語があります。
詳しくは
Perl 5 の C 拡張のアプリケーションプログラミングインタフェース
あるいは、配布キットに添付されているperlxs.htmlを参照して下さい。
Q2.)OSコマンド等をPerlから使用するのに、system関数だとうまくいくのですが、
バッククォート``だと出力が出てきません。どうしてでしょうか?
A2.)
バッククォートによって実行されたコマンドの出力はperlに戻されます。
すなわち、
$command = 'dir';
$output = `$command`;
のようにして、出力を左辺の変数にセットして、その結果を
加工するために使用されることが多いのです。これを単に
$command = 'dir';
`$command`;
とすると、標準出力はリダイレクトされているので、コンソールやブラウザには
出力されません。特に標準出力のリダイレクトが必要なければ
$command = 'dir';
system($command);
のようにsystem関数を使います。
Q3.) perlで有効桁数小数点以下第2位とかの設定はできるのでしょうか?
A3.) ラクダ本P254をご覧下さい。
例)
$a=12345.12345;
printf "%5.4f\n",$a;
printf "%5.2f\n",$a;
出力
Q4.)下記のようにして、0から20までのランダムな数をえようとしましたが、
どうしても出力してくれません!
A4.)ラクダ本の255ページを参照してください。
まず、srand()を使って、乱数の種を仕込みます。
srand(time^$$);
$deta=int(rand(20));
print $data,"\n";
Q5.)小数点処理(小数点以下の切り捨て、四捨五入)がよくわかりません。
例えば、$a=4220、とすると,
$tax = "$a" * 0.03;
print "$tax";
そして結果は 126.6 となります。どのようにすればいいのでしょうか。
A5.)
単純な切り捨てだとint()が利用できます。
切り上げはその応用です(元の数値に1を加算)。
四捨五入は+0.5してintを使用します。
$a = 126.6;
$b = 126.4;
$floor = int($a); #切り捨て
$ceil = ($a == int($a) ? $a : int($a+1)) ; #切り上げ(下記のコメントを参考のこと)
$floor_or_ceil_a = int($a+0.5); #四捨五入
$floor_or_ceil_b = int($b+0.5);
print "FLOOR=",$floor,"\n";
print "CEIL=$ceil\n","floor_or_ceil_a=",$floor_or_ceil_a,"\n";
print "floor_or_ceil_b=",$floor_or_ceil_b,"\n";
結果
FLOOR=126 #切り捨て
CEIL=127 #切り上げ
floor_or_ceil_a=127 #四捨五入
floor_or_ceil_b=126 #四捨五入
切り上げの場合、126.0 のようなケースでは、単に1を加えると 127 になってしまい、具合がよくありません。
これを回避するには、
(1) int した結果が、元の数と同じならば、元の数を使う。
(2) そうでない時は、元の数に 1 を加えて int する。
等の処理が必要になります。上記では、?:条件演算子を利用していますが、if等を使っても構いません。
<谷和さんに感謝>
いちいち面倒だという方は、POSIXモジュールを利用するとよいでしょう。
use POSIX;
$ceil1 = ceil(126.0);
$ceil2 = ceil(126.1);
print "126.0の切り上げ => $ceil1\n";
print "126.1の切り上げ => $ceil2\n";
【結果】
126.0の切り上げ => 126
126.1の切り上げ => 127
なお、上記を応用すると、数値のある桁の数字処理についての処理も同様にできます。
例えば、下1桁を切り捨てるには
$a=1755;
print $a,"\n";
$b = int($a/10) * 10;
print $b;
結果
1755
1750
この項は竹内弘昌さんのご協力を頂きました。ありがとうございました。
Q6.)
実行中のPerlスクリプトがあるディレクトリを知るにはどうすればよいでしょうか。
やり方はいろいろありますが、FindBinモジュールを使うのが簡単でしょう。
use FindBin qw($Bin);
print use FindBin qw($Bin);
また、FindBinモジュールを使うと、そのPerlスクリプトが置いてあるディレクトリをスクリプトの検索パスに追加することもできます。
use FindBin qw($Bin);
use lib "$Bin/";
Q7.)
階層になっているフォルダがあるのですが、再帰的にすべてのフォルダにあるファイルを取り出すにはどうすればよいでしょうか。
やり方はいろいろありますが、Find関連モジュールを使うと簡単に実現できます。
例)
use File::Find;
$dir = '/foo';
find(\&print_dir, $dir);
sub print_dir {
print $File::Find::name, "\n";
}
詳細は、モジュールの付属ドキュメントをご覧下さい。
Q8.)
プロンプト等からのキー入力による応答を自動化させたいのですが、どうすればよいでしょうか。
Perlではありませんが、telnet や ftp などの対話型のアプリケーションを自動駆動するチャット・スクリプトのようなものを書くときに重宝するTcl ベースのインタプリタ Expect という言語があります。
http://expect.nist.gov/
Perlでは、これをモジュール化したExpectモジュールというものがあります。
http://www.perl.com/CPAN/modules/by-module/Expect/
Q9.)
CSV(Comma-Separated Value:コンマ区切りデータ)から値を取り出したいのですが、どうすればよいでしょうか。
perlfaq4に回答があります。
perldoc -q delimited string
perlfaq4でも紹介されていますが、Perl5.6.0の標準モジュールであるText::ParseWordsモジュールを使うと簡単です。
例)
use Text::ParseWords;
$text = q/"語中に,がある","ABC,Inc","次はダブルクォートブランク","",裸英字,ABC,裸数字,123,'次はシングルクォートブランク','',"End"/;
@list = quotewords(",", 0, $text);
foreach $word ( @list ) {
# $word =~ s/\n//g; # 改行文字があれば取り除く
print ++$n, " : ", $word, "\n";
}
Text::ParseWordsモジュールの詳細は付属ドキュメントを参照してください。
perldoc Text::ParseWords
他のやり方としては、
http://www.din.or.jp/~ohzaki/perl.htm#CSV2Values
等が参考になるでしょう。
Q10.)
ファイルをコピーしたり移動したいのですが、どうすればよいでしょうか。
File関連モジュールのFile::copyモジュールを使うと簡単です。
例)
use File::Copy;
# ファイルのコピー
copy("file_A","file_B") or die;
# ファイルの移動
move("./file_D","../file_E") or die;
# ファイルの内容を標準出力にコピー(出力)
copy("file_C",\*STDOUT) or die;'
Q11.)
ファイルの中身が同じものかどうか比較したいのですが、どうすればよいでしょうか。
File関連モジュールのFile::Compareモジュールを使うと簡単です。
例)
use File::Compare;
if (compare("file1","file2") == 0) {
print "同じ内容\n";
} else {
print "別の内容\n";
}
Q12.)
"xxx.txt"のようなファイル名からxxxの部分だけ抜き出して表示したいのですが、どうすればよいでしょうか。
File::Basenameモジュールを使うとプラットフォーム毎に対応できるので便利です。
例)
use File::Basename;
fileparse_set_fstype("MacOS");
$basename = basename("lib/File/Basename.pm",".pm");
print $basename,"\n";
詳細は、モジュール付属のドキュメントを参照してください
Q13.)
多階層のディレクトリを一度に生成したり一度に削除したりしたいのですが、簡単な方法はないでしょうか。
File関連モジュールのFile::Pathモジュールを使うと簡単です。
例)
use File::Path;
#
mkpath(['/level_1/level_2/level_3', 'a1/b1'], 1, 0744);
# /level_1、./a1以下を全て削除
rmtree(['/level_1', 'a1'], 1, 1) or die;
詳細は、モジュール付属のドキュメントを参照してください
Q14.)
2 進数を16進数に変換したいのですが、どうすればいいのでしょうか。
2 進数で表現した文字列を一旦10進数の整数に変換して、それを sprintf で16進数にすれば実現できます。
Perl5.6 から2進数を0b1111(10進数の15)のように表現できるようになり、また、oct関数は2進数、8進数、16進数を10進数の整数に変換してくれる優れものです。oct関数の戻り値を、以下のように希望するパラメータと一緒にsprintf/printf の引数としてセットすればできあがりです。これを応用すれば、2進数、8進数、10進数、16進数の変換は実に簡単に行えます。
$val = "0b1111"; # "017", ""0x0f", "17"
$val = oct($val) if $val =~ /^0/;
printf("16進数 = 0x%x\n", $val);
printf("10進数 = %d\n", $val);
printf("8進数 = 0%o\n", $val);
printf("2進数 = %s\n", unpack("B16", pack("n", $val)));
値を一旦格納する場合は、sprintを使用すると簡単です。
$hex = sprintf("%x", $val);
Perl5.005以下で2進数を変換したい場合、以下のような処理方法があります。
$val = "1111";
# 10進数表記
$val = unpack("N", pack("B32",substr("0" x 32 . $val, -32)));
ご意見は、 電子メールにてお願い致します。
ホームページへ戻る。