【问题标题】:perl process filehandleperl 进程文件句柄
【发布时间】:2012-08-14 06:05:48
【问题描述】:

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

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

【问题讨论】:

    标签: perl process filehandle


    【解决方案1】:

    你是对的,date 只产生一个输出,一旦你读到它,缓冲区中就没有任何东西了。你可以这样做:

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

    另一种方法是使用 back tics:

    while (1) {
      print "Press any key: ";
      chomp( my $result=<STDIN> );
      print "now is: ".`date`."\n";
     }   
    

    【讨论】:

    • 您好,非常感谢您快速详细的回答。非常感谢。
    【解决方案2】:

    您的程序按说明运行。 date 命令返回单行,您正在尝试读取文件末尾

    正确的方法是:

    #! /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(...) 是另一种双引号字符串的方法。这允许您使用引号而不用反斜杠引用它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-18
      • 2015-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-10
      • 1970-01-01
      相关资源
      最近更新 更多