Perl Perl_0
Perl リストコンテキストで「 STDIN 」を利用する (0x2c)

Perl について、復習を兼ねて断片的な情報を掲載して行く連載その 0x2c 回。
Perl で、<STDIN> をリストコンテキストで使った場合の動作を確認する。
スカラコンテキストでの動作を再確認する
「 Perl <STDIN> でキーボードから入力を受け付ける それと chomp 演算子 (0x16) 」では、<STDIN> をスカラコンテキストで利用した場合の動作を、 chomp の動作とともに確認しました。
まずは、スカラコンテキストで利用した際の動作を再確認しましょう。
$line = <STDIN>;
if ($line eq "\n"") {
print "Blank line.\n";
} else {
print "Input was $line";
}
この例では、1 行目で <STDIN> の入力を待ち受ける変数が、シジル「 $ 」によってスカラ変数になっていますので、Perl はスカラコンテキストの文脈だと判断します。
この (スカラコンテキストの) 場合、<STDIN> は改行をトリガーとして入力受付を打ち切るので、取得できる値は入力された 1 行分のデータのみです。
3 行目の if 文の条件式では、仮に入力が改行文字のみだった場合に、真 と判定し、そのことをユーザに伝えるメッセージを表示します。
改行文字の入力までに、何らかの文字列の入力があれば、if 文の条件式は 偽 と判定されるため、else ブロックにある 6 行目の print 文が実行され入力内容が表示されます。
この print 文で「 "" 」の末尾に改行文字を含めていないのは、指定された変数 $line が改行文字を持っているからです。
リストコンテキストで入力行を 1 度に受け取る
同じ <STDIN> をリストコンテキストで使ってみます。
リストコンテキストで <STDIN> を使う最も簡単な方法は、おそらく次の様に配列変数を使うことです。
@line = <STDIN>;
入力されたデータをただ表示したいだけなら、もっと簡単な方法があります。
次の例は、print 文がリストコンテキストであることを利用しています。
print <STDIN>;
リストコンテキストで指定された <STDIN> は、複数行のデータを一度に受け取ることが出来ます。
<STDIN> で受け取るデータの入力元がファイルだった場合、Perl は「 ファイルの終わり 」まで読み込むと入力の受付けを打ち切ります。
しかし、通常 <STDIN> の入力元は「 標準入力 」が指定されていて、それはほとんどの場合、あなたや私のキーボードを指しています。
キーボードから「 ファイルの終わり 」に代わる命令を出す、つまり「 入力の終了 」を Perl に知らせるにはどうすればよいのでしょうか。
キーボードからの入力を終了する
標準入力 (通常はキーボード) から、Perl に (正確には Perl が動作しているシステムに) 入力の終わりを告げるには、キーボードより「 Ctrl + D 」をタイプします。
「 Perl ループ処理 (while その 2 "無限ループ") (0x0f) 」では、「 Ctrl + C 」によってプログラムを強制的に停止する方法を確認しましたが、「 Ctrl + D 」はプログラムを停止するのではなく、入力の完了を指示するものです。
Perl プログラムが動作するシステムが DOS/Windows の場合は、「 Ctrl + D 」の代わりに「 Ctrl + Z 」をタイプします。
というわけで、次の様に「 Ctrl + D 」をタイプする様にメッセージを表示すると親切です。
print "Enter some lines, then press Ctrl + D:\n";
@line = <STDIN>;
仮に「 Ctrl + C 」をタイプした場合、それはプログラムの強制終了を意味するため、Perl プログラムは以降の処理を中断して、なにもせずに終了します。
配列 - 奇妙な空白
<STDIN> から受け取った入力行を配列変数に格納した後、print 文で表示してみます。
print "Enter some lines, then press Ctrl + D:\n";
@line = <STDIN>;
print "@line";
このプログラムを実行して次の文字列を入力しました。
Hello, Perl.
I enter strings from <STDIN>.
With what results ?
結果は次の様になります。
Hello, Perl.
I enter strings from <STDIN>.
With what results ?
2 行目以降の行頭に、おかしな空白が混入しています。この空白はいったいどこから来たのでしょうか。
ここで試しに、print 文の配列を次の様に指定してみます。
print @line;
先の print 文との違いは、配列変数がクォートされていないことです。
結果は次の様になります。
Hello, Perl.
I enter strings from <STDIN>.
With what results ?
行頭の奇妙な空白はいなくなりました。
どうやら、配列のクォーテーションに問題がありそうです。
0x2c -> 0x2d へ
リストコンテキストで <STDIN> を使うにあたっては、読み込むデータのサイズに注意した方が良いそうです。
なぜなら、リストコンテキストの <STDIN> は、すべての行を 1 度に読み込むからです。
読み込まれた行は一時的にメモリを占有しますので、そのサイズが大きければ大きいほど大量のメモリを占有してしまいます。
例えば、400MB のデータの読み込みでは、最低で 1GB のメモリを占有するとのことです。
最近のコンピュータは、潤沢なメモリを搭載しているケースが多いと思いますが、それでもやはり、大きなデータを扱う場合は、一度に読み込まない様な工夫が必要とのことです。
次回は「 配列の奇妙な空白 」を説明します。
参考情報は以下の書籍を中心に Wikipedia および各 Web サイト。それと詳しい先輩。
参考 :「Randal L. Schwartz, brian d foy, Tom Phoenix 共著 近藤 嘉雪 訳「初めての Perl 第 6 版」(オライリー・ジャパン発行 ISBN978-4-87311-567-2)」
次回 (0x2d) へ続く。
過去記事 RSS
Perl mp2 翻訳 Web コンテンツ圧縮の FAQ (d228)
Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227)
Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226)
Perl mp2 翻訳 テンプレートシステムの選択 (d225)
Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224)
Perl mp2 翻訳 チュートリアル (d223)
Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227)
Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226)
Perl mp2 翻訳 テンプレートシステムの選択 (d225)
Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224)
Perl mp2 翻訳 チュートリアル (d223)