2

ファイルハンドルを使用してプロセスから読み取る方法を学ぼうとしています。次のプログラムを使用して、「date」コマンドと参照からファイルハンドルを開くプログラムを作成しようとしました。

 #!/usr/bin/perl
 use warnings;
 use diagnostics;
 use strict;

 open DATE, 'date|' or die "Cannot pipe from date: $!";
 my $now;

 while (1) {
  print "Press any key: ";
  chomp( my $result=<STDIN> );

  $now = <DATE>;

  print "\$now is: $now\n";

 }   

これは 1 回、または最初は機能しますが、後続の「ループ」は while (1) を介して行われ、2 回目には「$now の初期化されていない値」に関するエラーが発生します。さらに奇妙なことに、エラーは 2 番目のループの後に消えますが、「date」からのデータは $now 変数に取り込まれません。

これは、最初の実行後にファイルハンドルが閉じられていることを示している可能性があると思いますが、そうであるかどうかはわかりません。私はちょうど今 perl を学んでいます。これは簡単だと思いますが、この言語について十分な経験がありません。

誰でもこれについて私にガイダンスを提供できますか? ループを最初に実行した後、DATE ファイルハンドルが開いたままになることは期待できませんか?

この時点でのプログラムからの出力は次のとおりです。

 $ perl ./test.perl
 Press any key:
 $now is: Fri Aug 17 15:00:27 EDT 2012

 Press any key:
 Use of uninitialized value $now in concatenation (.) or string at ./test.perl
         line 16, <DATE> line 1 (#1)
     (W uninitialized) An undefined value was used as if it were already
     defined.  It was interpreted as a "" or a 0, but maybe it was a mistake.
     To suppress this warning assign a defined value to your variables.

     To help you figure out what was undefined, perl will try to tell you the
     name of the variable (if any) that was undefined. In some cases it cannot
     do this, so it also tells you what operation you used the undefined value
     in.  Note, however, that perl optimizes your program and the operation
     displayed in the warning may not necessarily appear literally in your
     program.  For example, "that $foo" is usually optimized into "that "
     . $foo, and the warning will refer to the concatenation (.) operator,
     even though there is no . in your program.

 $now is:
 Press any key:
 $now is:
 Press any key:
 $now is:
 Press any key:
 $now is:
 Press any key: ^C     
4

2 に答える 2

4

あなたは正しいです。date単一の出力のみを生成し、それを読み取ると、バッファには何も残りません。次のようなことができます。

while (1) {
  # ...
  open DATE, 'date|' or die "Cannot pipe from date: $!";
  $now = <DATE>;
  close DATE;
  # ...
  print "\$now is: $now\n";

}   

もう 1 つの方法は、バック ティックを使用することです。

while (1) {
  print "Press any key: ";
  chomp( my $result=<STDIN> );
  print "now is: ".`date`."\n";
 }   
于 2012-08-17T19:15:11.303 に答える
0

あなたのプログラムは述べたように動作しています。date コマンドが 1 行を返しているのに、 end of fileを読み込もうとしています。

正しい方法は次のとおりです。

#! /usr/bin/env perl
use warnings;
use diagnostics;
use strict;
use autodie;
use feature qw(say);

open my $date, "|-", "date";

while (my $now = <$date>) {
   print "Press any key: ";
   chomp( my $result=<STDIN> );

   say "\$now is: $now";
}

そして、プログラムは単一のループを実行します。

いくつかのこと:

  • use feature qw(say);最後に入れ続ける必要がないことを除いて、のsayようなコマンドを使用できます。print\n
  • use autodie;openステートメントをテストせずに自動的に終了させます。とにかく死ぬつもりopenなら、Perl にやらせてみませんか。
  • 3 パラメーターopenコマンドを使用することをお勧めします。また、ファイル ハンドルにスカラーを使用することもできます。

おそらくあなたが望むのは次のようなものです:

#! /usr/bin/env perl
use warnings;
use diagnostics;
use strict;
use autodie;
use feature qw(say);

for(;;) {
    print "Press Return to continue...";
    <STDIN>;
    chomp ( my $date = qx(date) );
    say qq(\$date = "$date");
}
  • 逆引用符よりも優先される引用符の実行qx(...)を意味します。
  • これqq(...)は、文字列を二重引用符にする別の方法です。これにより、バックスラッシュで引用せずに引用符を使用できます。
于 2012-08-17T20:19:57.857 に答える