【问题标题】:Pass a hash object from one perl script to another using system使用系统将哈希对象从一个 perl 脚本传递到另一个
【发布时间】:2015-10-12 16:35:39
【问题描述】:

我有以下 perl 脚本,它接收参数文件并将其存储到哈希中。我想修改并将此哈希传递给我正在使用系统命令调用的另一个 perl 脚本:

script1.pl

#!/usr/bin/perl -w
# usage perl script1.pl script1.params
# script1.params file looks like this:
# PROJECTNAME=>project_dir
# FASTALIST=>samples_fastq.csv

use Data::Dumper;

my $paramfile = $ARGV[0];

# open parameter file
open PARAM, $paramfile or die print $!;

# save it in a hash
my %param;
while(<PARAM>)
{
        chomp;
        @r = split('=>');
        $param{$r[0]}=$r[1];
}

# define directories
# add to parameters' hash
$param{'INDIR'} = $param{'PROJECTNAME'}.'/input';
$param{'OUTDIR'} = $param{'PROJECTNAME'}.'/output';

.... do something ...
# @samples is a list of sample names
foreach (@samples)
{
        # for each sample, pass the hash values & sample name to a separate script
        system('perl script2.pl <hash> $_');
}

script2.pl

#!/usr/bin/perl -w
use Data::Dumper;
## usage <script2.pl> <hash> <samplename>
# something like getting and printing the hash
my @string = $ARGV[0];
print @string;

如果您能帮助我展示如何传递和获取哈希对象(在第二个脚本中打印哈希对象这样简单的事情就可以了),那么我将不胜感激。

谢谢!

【问题讨论】:

标签: perl hash system


【解决方案1】:

您正在寻找的是一种称为序列化的东西。由于指针和缓冲区等各种有趣的东西,很难以在进程之间传递的方式直接表示内存结构。

所以你需要把你的哈希变成简单到可以一次性交出的东西。

我认为这三个关键选项:

  • Storable - 一个 perl 核心模块,可让您 freezethaw 用于此类目的的数据结构。
  • JSON - 基于文本的类似哈希结构的表示。
  • XML - 有点像 JSON,但优势/劣势略有不同。

您应该使用哪个取决于您的数据结构有多大。

Storable 可能是最简单的,但它不会特别便携。

还有Data::Dumper 也是一个选项,因为它打印数据结构。不过,一般来说,我建议它具有上述所有缺点 - 您仍然需要像 JSON/XML 一样解析它,但它也不是可移植的。

使用Storable的示例:

use strict;
use warnings;
use Storable qw ( freeze  );
use MIME::Base64;

my %test_hash = (
    "fish"   => "paste",
    "apples" => "pears"
);

my $frozen = encode_base64 freeze( \%test_hash );

system( "perl", "some_other_script.pl", $frozen );

调用:

use strict;
use warnings;
use Storable qw ( thaw );
use Data::Dumper;
use MIME::Base64;

my ($imported_scalar) = @ARGV; 
print $imported_scalar;
my $thing =  thaw (decode_base64 $imported_scalar ) ;
print Dumper $thing;

或者:

my %param =  %{ thaw (decode_base64 $imported_scalar ) };
print Dumper \%param;

这将打印:

BAoIMTIzNDU2NzgEBAQIAwIAAAAKBXBhc3RlBAAAAGZpc2gKBXBlYXJzBgAAAGFwcGxlcw==
$VAR1 = {
          'apples' => 'pears',
          'fish' => 'paste'
        };

JSON 执行相同操作 - 其优点是可以作为纯文本和通用格式传递。 (大部分语言都可以解析JSON):

#!/usr/bin/env perl
use strict;
use warnings;
use JSON; 

my %test_hash = (
    "fish"   => "paste",
    "apples" => "pears"
);
my $json_text = encode_json ( \%test_hash );
print "Encoded: ",$json_text,"\n";

system( "perl", "some_other_script.pl", quotemeta $json_text );

调用:

#!/usr/bin/env perl
use strict;
use warnings;
use JSON;
use Data::Dumper;

my ($imported_scalar) = @ARGV; 
$imported_scalar =~ s,\\,,g;
print "Got: ",$imported_scalar,"\n";

my $thing =  decode_json $imported_scalar ;

print Dumper $thing;

不幸的是,需要引号和删除斜线,因为外壳会插入它们。如果您尝试做这种事情,这是常见的问题。

【讨论】:

  • 很抱歉我不经常使用 perl,但我会尝试理解你的答案并查找一些东西。谢谢
  • 那么你应该知道——你想做的事情比你想象的要难。 perlipc下有一整章讲进程间通信
  • 那么,我可以将哈希转换为数组并将其传递给脚本吗?或者它的工作原理与您所说的相似?
  • 没有。您不能在命令行上传递 any 复杂的数据结构。只有文字(ish)。
  • 感谢代码!在上面显示的脚本中,可以将 $thing 对象存储在新的哈希中吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-04
  • 2012-06-16
  • 1970-01-01
  • 1970-01-01
  • 2018-06-14
  • 1970-01-01
相关资源
最近更新 更多