【问题标题】:Combining Input from STDIN and File in Perl在 Perl 中组合来自 STDIN 和文件的输入
【发布时间】:2012-04-24 18:44:40
【问题描述】:

我希望我的 Perl 脚本能够做到这一点

./code1 param1 param2 param3 | perl myperlscript.pl param1 param2

所以 Perl 脚本应该接受 3 个输入:

  1. 参数1
  2. 参数2
  3. ./code1 param1 param2 param3 的输出

我的 Perl 代码中有这个,但它出错了:

my $param1 = $ARGV[0] || "control.fst";
my $param2  = $ARGV[1] || "target.fst";

my @control_header = `grep ">" $param1`;
my @target_header = `grep ">" $param2`;
# Later to do something with those arrays

while (<>) {
 # do something again
}

我知道我可以为./code1 制作临时输出。 但由于输出非常大,我更喜欢用管道传输。 请告知正确的方法。

【问题讨论】:

  • 请解释您所说的出错是什么意思。你有什么问题?

标签: perl file file-handling


【解决方案1】:

虽然@ARGV 不为空,但&lt;&gt; 运算符将从那里指定的文件中读取。一旦@ARGV 用尽,从STDIN 继续读取。

如果在读取 @control_header@target_header 数组后显式清空 @ARGV,则程序应该可以按预期运行。或者,您可以使用 &lt;STDIN&gt;STDIN 显式读取。

但我认为最好使用 Perl 从文件参数中读取您需要的信息。这个程序演示了这个想法

use strict;
use warnings;

my $param1 = shift || 'control.fst';
my @control_header = do {
  open my $fh, '<', $param1 or die qq(Unable to open file "$param1": $!);
  grep />/, <$fh>;
};

my $param2 = shift || 'target.fst';
my @target_header = do {
  open my $fh, '<', $param2 or die qq(Unable to open file "$param2": $!);
  grep />/, <$fh>;
};

while (<STDIN>) {
  # do something again
}

【讨论】:

    【解决方案2】:

    根据您的情况,从@ARGV 中删除param1param2

    my $param1 = shift;
    my $param2 = shift;
    

    现在您可以使用处理来自code1 的管道输出

    while (<>) {
      ...;
    }
    

    更通用的解决方案是使用bash process substitution,如

    perl myperlscript.pl <(./other param1 param2) <(./code1 param1 param2 param3)
    

    这使得othercode1 的输出从命名管道中出现

    while (<>) {
      ...;
    }
    

    会愉快地处理。

    【讨论】:

      【解决方案3】:

      更多 perlish 代码如下:

      #!/usr/bin/perl
      
      use strict;
      use warnings;
      
      my $param1 = $ARGV[0] || "control.fst";
      my $param2 = $ARGV[1] || "target.fst";
      
      my @control_header;
      my @target_header;
      
      open FH, "<$param1" or die;
      map { push @control_header, $1 if /^(.*?>.*?)[\n\r]*$/ } (<FH>);
      close FH;
      
      open FH, "<$param2" or die;
      map { push @target_header,  $1 if /^(.*?>.*?)[\n\r]*$/ } (<FH>);
      close FH;
      
      ...                                                                              
      
      while (<STDIN>) {                                                                
        ...                                                                            
      }                                                                                
      

      【讨论】:

      • 您可以选择扩展die 输出并将die; 替换为die "Cannot open file $param1"; 或类似...
      • 虚空上下文中的地图根本不会消失。
      • 您真的不应该鼓励使用 typeglob 文件句柄或open 的两参数形式。此外,die 字符串应包含 $! 以获取信息。
      【解决方案4】:

      有两种选择。

      1) 读取标准输入

      while (<STDIN>) {
      chomp();  
      # do something again
      
      }
      

      2) 从 Perl 脚本调用第一个程序并处理其输出。见recipe 16.05 in Perl Cookbook

      open(PRG,"./code1 param1 param2 param3|") or die $!;
      while (<PRG>) {
      chomp();  
      # do something again
      
      }
      

      【讨论】:

        猜你喜欢
        • 2017-05-21
        • 1970-01-01
        • 2017-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-28
        • 2011-03-09
        相关资源
        最近更新 更多