|
|
Perlプログラム作成の標準入力と コマンドライン引数 |
H.Kamifuji . |
値を指定の書式で整形し、文字列として取得する方法を確認します。例えば数値を16進数や8進数にしたり桁数を指定して0詰めで表示したりすることが出来ます。 当ページでは、Linux CentOS7 の Gnome で動作テストしています。 |
|
perlのプログラムを実行する時に合わせて引数を記述しperlのプログラム内で参照することが可能です。このようにプログラムの実行時に指定する引数をコマンドライン引数と言います。 コマンドライン引数を指定するには次のように記述します。 perl プログラム名 引数1 引数2 ...コマンドライン引数は複数指定可能です。引数はスペースで区切って続けて記述します。例えば「90」「75」と言う2つの値をコマンドライン引数に指定するには次のように記述します。 perl sample.pl 90 75コマンドライン引数に記述された値はプログラムの中で参照することが可能です。コマンドライン引数は特別な配列である「@ARGV」の要素として格納されますので、各要素を取り出すことでコマンドライン引数を参照することが可能です。 my $kokugo = $ARGV[0]; my $sansuu = $ARGV[1];コマンドライン引数を使えば、プログラムを実行する度に指定した値を使ってプログラムを実行することが可能です。 では簡単なプログラムで確認して見ます。 test1-1.pl サンプルプログラム下記のサンプルを実行してみよう。# コマンドライン引数の取得 # use strict; use warnings; use utf8; binmode STDIN, ':encoding(cp932)'; binmode STDOUT, ':encoding(cp932)'; binmode STDERR, ':encoding(cp932)'; my ($kokugo, $sansuu); if (@ARGV == 2){ my $kokugo = $ARGV[0]; my $sansuu = $ARGV[1]; print "国語=$kokugo, 算数=$sansuu\n"; if ($kokugo > 75 && $sansuu > 75){ print "合格です\n"; }else{ print "不合格です\n"; } }else{ print "引数を2つ指定して下さい\n"; }上記を「test1-1.pl」の名前で保存してから次のように実行して下さい。 ![]() 今回のサンプルではコマンドライン引数を2つ使ったサンプルです。そこでまずコマンドライン引数が2つ指定されているかどうかをチェックしています。2つ指定されていない場合はエラー表示を行って終了します。 では次のようにコマンドライン引数を2つ指定してみます。 ![]() コマンドライン引数として指定された2つの値を取得し、値の判定を行っています。最初の実行時には不合格、次の実行時には合格となっています。このように同じプログラムを使って実行時に別の値に対して処理を行うことが出来るようになります。 Linux 環境での実行結果は、下記です。シフトJIS で出力されるので nkf -w で UTF-8 に変換しています。 [xxxxxxxx@dddddddddd Stdin]$ perl test1-1_u.pl | nkf -w 引数を2つ指定して下さい [xxxxxxxx@dddddddddd Stdin]$ perl test1-1_u.pl 90 55 | nkf -w 国語=90, 算数=55 不合格です [xxxxxxxx@dddddddddd Stdin]$ perl test1-1_u.pl 76 80 | nkf -w 国語=76, 算数=80 合格です [xxxxxxxx@dddddddddd Stdin]$ |
前のページではプログラムの起動時にコマンドライン引数を使用して値を指定する方法を確認しました。ここではプログラムを実行後にユーザーからキーボードを使って値を入力してもらう方法を確認します。 プログラム実行中に何らかの入力を行うには行入力演算子の「<>」演算子を使用します。 変数 = <ファイルハンドル>上記では指定したファイルハンドルから1行読み込んで変数に格納します。改行文字が現れるまでの値が1行です。 ファイルハンドルはまた別の箇所で詳しく説明しましが、現在開いているファイルを識別するためのものです。今回はファイルからの読み込みではなくキーボードから値を読み込みます。キーボードからの入力を行うには特別なファイルハンドルである「STDIN」を使用します。 変数 = <STDIN>上記のように記述すると、「Enter」キーが押されるまでキーボードから入力された文字を変数に格納します。この時、「Enter」キーも改行として合わせて取得します。 例えば次のように記述します。 my $line =このように記述すると、プログラムの実行中にこの部分に差し掛かるといったんプログラムの実行が中段し、キーボードからの入力待ちとなります。ユーザーがキーボードから値を入力して「Enter」キーを押すと入力された値が変数に格納されて次の行からプログラムが再開します。 なおキーボードから入力された値には改行が含まれています。改行を取り除くには「chomp」関数を使用します。(chomp関数については「chomp関数」を参照して下さい)。 my $line =では簡単なプログラムで確認して見ます。 test2-1.pl サンプルプログラム下記のサンプルを実行してみよう。# 標準入力からの値の取得 # use strict; use warnings; use utf8; binmode STDIN, ':encoding(cp932)'; binmode STDOUT, ':encoding(cp932)'; binmode STDERR, ':encoding(cp932)'; print "名前を入力して下さい\n"; my $line =上記を「test2-1.pl」の名前で保存してから次のように実行して下さい。 ![]() プログラムを実行すると、名前の入力を求められます。そこで何か入力してから「Enter」キーを押して下さい。 ![]() もう一度今度は成績の入力を求められます。同じように何か入力して「Enter」キーを押して下さい。 ![]() 入力された値を画面に表示して終了します。 Linux 環境での実行結果は、下記です。シフトJIS で出力されるので nkf -w で UTF-8 に変換しています。 [xxxxxxxx@dddddddddd Stdin]$ perl test2-1_u.pl | nkf -w masuzoe 3 名前を入力して下さい 成績を入力して下さい 名前:masuzoe, 成績:3 [xxxxxxxx@dddddddddd Stdin]$パイプライン経由で出力では、上手くフラッシュリングされないので、プログラムを下記のように書き換えて実行してみました。 # 標準入力からの値の取得 # use strict; use warnings; # use utf8; # デフォルトの文字コードで実行 # binmode STDIN, ':encoding(cp932)'; # binmode STDOUT, ':encoding(cp932)'; # binmode STDERR, ':encoding(cp932)'; print "名前を入力して下さい\n"; my $line =上記の変更後の実行結果は、下記です。 [xxxxxxxx@dddddddddd Stdin]$ perl test2-1_u.pl 名前を入力して下さい masuzoe 成績を入力して下さい 3 名前:masuzoe, 成績:3 [xxxxxxxx@dddddddddd Stdin]$ |
標準入力からある条件を満たすまで繰り返し入力を行うという処理はよく使われます。例えば次のように記述します。 while (defined(my $line =上記の場合、while文の条件式の箇所で標準入力から1行読み込みます。条件式が真の場合、読み込んだ行から改行を取り除き画面に出力しています。 行入力演算子である「<>」はファイルの終端を読み込むと未定義値(undef)を返します。そこで「defined」関数を使い未定義値(undef)が返されたときに繰り返しを終了させています。未定義値(undef)自体が偽となるため、「defined」関数を使用しなくてもファイルの終端に達すると繰り返しは終了しますが、未定義値以外で改行無しの「0」などを読み込んだ場合でも条件式は偽となるため未定義値(undef)かどうかを判別する方が安心です。 今回のように標準入力から値を読み込む場合はファイルの終端と言うものはありませんので、ファイルに終端に相当する「Ctrl+z」を入力して「Enter」キーを押すか、または繰り返し処理の本文の中で何からの条件判断を行って繰り返し処理を抜けるようにします。 なお「define」関数を記述した方がいいと先ほど書きましたが、現在では「defined」関数を記述しなくても次のように記述するだけで「define」関数が記述された時と同じ処理を行ってくれるようです。 while (my $line =またwhile文(とfor文)の条件式の中に記述する場合にはデフォルト変数の「$_」を使って次のように記述することも可能です。 while (ただし上記のデフォルト変数「$_」はブロック内だけのローカル変数ではありません。よってwhile文やfor文の外側で変数「$_」を使っていた場合は値が書き換えられますので注意して下さい。 なおfor文の場合は次のように記述します。 for (;どちらの場合も使い方は同じです。 では簡単なプログラムで確認して見ます。 test3-1.pl サンプルプログラム下記のサンプルを実行してみよう。# while/for文を使い標準入力から繰り返し値を取得 # use strict; use warnings; use utf8; binmode STDIN, ':encoding(cp932)'; binmode STDOUT, ':encoding(cp932)'; binmode STDERR, ':encoding(cp932)'; print "while文による繰り返し\n"; while (my $line =上記を「test3-1.pl」の名前で保存してから次のように実行して下さい。 ![]() プログラムを実行すると入力待ちとなります。何か入力してから「Enter」キーを押すと入力された内容が画面に表示されます。 ![]() 引き続き入力待ちとなりますので今度は「Ctrl+z」キーを押して(画面では「^Z」と表示されます)から「Enter」キーを押します。 ![]() するとwhile文は抜けて次の処理に移ります。次はfor文で同じ処理を行っていますので、何か入力して「Enter」キーを押せば入力された内容を表示します。 ![]() 引き続き入力待ちとなりますので「Ctrl+z」キーを押してから「Enter」キーを押すとプログラムが終了します。 ![]() Linux 環境での実行結果は、下記です。シフトJIS で出力されるので nkf -w で UTF-8 に変換しています。 [xxxxxxxx@dddddddddd Stdin]$ perl test3-1_u.pl | nkf -w masuzoe koike yuriko while文による繰り返し masuzoe for文による繰り返し koike yuriko 終了しました [xxxxxxxx@dddddddddd Stdin]$パイプライン経由で出力では、上手くフラッシュリングされないので、プログラムを下記のように書き換えて実行してみました。 # while/for文を使い標準入力から繰り返し値を取得 # use strict; use warnings; # use utf8; # デフォルトの文字コードで実行 # binmode STDIN, ':encoding(cp932)'; # binmode STDOUT, ':encoding(cp932)'; # binmode STDERR, ':encoding(cp932)'; print "while文による繰り返し\n"; while (my $line =上記の変更後の実行結果は、下記です。 Linux の場合は、ループから抜けるには ^Z でなく ^D を利用します。 [xxxxxxxx@dddddddddd Stdin]$ perl test3-1_u.pl while文による繰り返し masuzoe masuzoe for文による繰り返し koike yuriko koike yuriko 終了しました [xxxxxxxx@dddddddddd Stdin]$ |
|