【问题标题】:Passing hash reference as an argument to perl script from perl script将哈希引用作为参数从 perl 脚本传递给 perl 脚本
【发布时间】:2015-07-17 09:34:29
【问题描述】:

我想将哈希引用作为参数从一个 perl 脚本 (script1.pl) 传递给另一个 perl 脚本 (script2.pl)。这就是我的代码的样子:

----------------------------script1.pl---------------- ------------------

#!/usr/bin/perl -w

use strict;
use warnings;

my %hash = (
'a'      => "Harsha",
'b'      => "Manager"
);

my $ref = \%hash;

system "perl script2.pl $ref";

----------------script2.pl---------------- ------------------

#!/usr/bin/perl -w

use strict;
use warnings;

my %hash = %{$ARGV[0]};

my $string = "a";

if (exists($hash{$string})){
    print "$string = $hash{$string}\n";
}

这是输出错误:

sh: -c: line 0: syntax error near unexpected token `('
sh: -c: line 0: `perl script2.pl HASH(0x8fbed0)'

我想不出传递引用的正确方法。

【问题讨论】:

标签: perl hash reference


【解决方案1】:

哈希是一种内存数据结构。进程“拥有”自己的内存空间,其他进程不能只访问它。如果您考虑一下,我相信您会很快发现原因。

哈希引用是该内存位置的地址。即使其他进程可以“理解”它,它仍然无法访问内存空间。

我们在这里讨论的实际上是一个相当大的概念——进程间通信或 IPC——以至于文档中有一整章都在讨论它,称为 perlipc

总而言之——你不能做你想做的事。在进程之间共享内存比你想象的要困难得多。

您可以做的是来回传输数据 - 不是通过引用,而是通过包含的实际信息。

对于您的示例,我建议您使用 JSON 来完成这项工作,因为这样您就可以对哈希进行编码和解码:

#!/usr/bin/perl -w

use strict;
use warnings;

use JSON;

my %hash = (
    'a' => "Harsha",
    'b' => "Manager"
);

my $json_string = to_json( \%hash );

print $json_string;

这给出了:

{"b":"Manager","a":"Harsha"}

然后你可以'传递'你的$json_string - 无论是在命令行上,但请记住,如果你不小心,它中的任何空格都会混淆@ARGV - 或通过STDIN

然后在你的子进程中解码:

use strict;
use warnings;

use JSON;

my $json_string = '{"b":"Manager","a":"Harsha"}';

my $json = from_json ( $json_string );

my $string = "a";

if (exists($json -> {$string} )){
    print "$string = ",$json -> {$string},"\n";
}

(您可以通过以下方式使其与您的代码更相似:

my $json = from_json ( $json_string );
my %hash = %$json;

其他选项是:

  • 使用Storable - 冻结和解冻(内存)或存储和检索(磁盘)
  • 使用IPC::Open2 并在STDIN 上发送数据。

确实有多种选择 - 看看perlipc。但不幸的是,这并不像“只是传递一个参考”那么简单。

【讨论】:

  • 很好的解释。您也可以使用FreezeThaw 并将冻结的字符串传递到ARGV..
  • 没有遇到这种情况,但已经设法通过Storable 完成类似的操作。我不建议这样做的主要原因是因为我不完全确定冻结的标量是否容易在命令行上传递,因为二进制内容。
【解决方案2】:

使用Storable 将数据存储在第一个脚本中并从其他脚本中检索。

firstscript.pl

store (\%hash, "/home/chankey/secondscript.$$") or die "could not store";
  system("perl", "secondscript.pl", $$) == 0 or die "error";

secondscript.pl

my $parentpid = shift;
my $ref = retrieve("/home/chankey/secondscript.$parentpid") or die "couldn't retrieve";
print Dumper $ref;

您已收到 $ref 中的 %hash。现在按照你想要的方式使用它。

【讨论】:

    【解决方案3】:

    您不能将引用从一个脚本传递到另一个脚本 - 该引用仅在当前运行的 perl 实例中才有意义。

    您需要在第一个脚本中“序列化”数据,然后在第二个脚本中“反序列化”它。

    【讨论】:

    • 我该怎么做呢?谢谢。
    【解决方案4】:

    你调用 perl 文件的方式是错误的。 只需更改调用方式即可。

    Script1.pl
    ---------------------------------
    
    #!/usr/bin/perl -w
    
    use strict;
    use warnings;
    
    my %hash = (
        'a'      => "Harsha",
        'b'      => "Manager"
    );
    
    system("perl","script2.pl",%hash);
    

    在另一个 perl 脚本中使用这个%hash,如下所示。

    Script2.pl
    ----------------------------------
    
    #!/usr/bin/perl -w
    
    use strict;
    use warnings;
    
    my %hash = @ARGV;
    
    my $string = "a";
    
    if (exists($hash{$string})){
        print "$string = $hash{$string}\n";
    }
    

    输出是

    a = Harsha
    

    【讨论】:

    • 你确定这有效吗?看起来不应该。
    • @Sobrique 在这种情况下它确实有效,因为%hashsystem 调用中被展平,所以它实际上相当于system("perl", "script2.pl", "a", "Harsha", "b", "Manager");。它不适用于嵌套的数据结构、对象或一些边缘情况,因此我将序列化数据。
    猜你喜欢
    • 2017-04-01
    • 2012-10-07
    • 1970-01-01
    • 2015-09-21
    • 1970-01-01
    • 1970-01-01
    • 2021-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多