1

I have the following perl script, that takes in a parameters' file and stores it into a hash. I want to modify & pass this hash to another perl script that I am calling using the system command:

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;

If you can help me showing how to pass and get the hash object (something simple like printing the hash object in the second script would do), then I'd appreciate your help.

Thanks!

1

1 Answer 1

7

What you're looking for is something called serialisation. It's difficult to directly represent a memory structure in such a way as to pass it between processes, because of all sorts of fun things like pointers and buffers.

So you need to turn your hash into something simple enough to hand over in a single go.

Three key options for this in my opinion:

  • Storable - a perl core module that lets you freeze and thaw a data structure for this sort of purpose.
  • JSON - a text based representation of a hash-like structure.
  • XML - bit like JSON, but with slightly different strengths/weaknesses.

Which you should use depends a little on how big your data structure is.

Storable is probably the simplest, but it's not going to be particularly portable.

There's also Data::Dumper that's an option too, as it prints data structures. Generally though, I'd suggest that has all the downsides of all the above - you still need to parse it like JSON/XML but it's also not portable.

Example using 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 );

Calling:

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;

Or:

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

This will print:

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

Doing the same with JSON - which has the advantage of being passed as plain text, and in a general purpose format. (Most languages can parse 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 );

Calling:

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

Need the quotemeta and the removal of slashes unfortunately, because the shell interpolates them. This is the common problem if you're trying to do this sort of thing.

Sign up to request clarification or add additional context in comments.

7 Comments

I am sorry I don't use perl on a regular basis, but I will try to understand your answer and lookup some stuff. Thanks
Then you should know - what you're trying to do is harder than you think. There's a whole chapter on inter process communication under perlipc
So, can I convert a hash to an array and pass it to a script? Or it works similar to what you are saying?
No. You can't pass any complex data structure on the command line. Only text (ish).
Thanks for the code! In your script that you showed above, can the $thing object be stored in a new hash?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.