2

我正在尝试学习如何使用文件句柄从进程中读取。我试图编写一个程序,从“日期”命令打开一个文件句柄,并使用以下程序按要求引用它:

 #!/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";

 }   

这工作一次,或最初工作,但随后通过 while (1) 进行“循环”,第二次我收到关于“$ now 的未初始化值”的错误。更奇怪的是,错误在第二次循环后消失了,但来自“日期”的数据从未填充到 $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";

}   

另一种方法是使用背部抽动:

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

您的程序按说明工作。date 命令返回单行,您正在尝试读取pass the 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 为你做这件事。
  • 三参数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 回答