1

I want to pass two file lists to my perl script and have them handled with Getopt::Long for storing an array (via a reference) in a dictionary.

#!/usr/bin/env perl

# author:sb2


use strict;
use warnings;
use Getopt::Long;
use File::Basename;
use Data::Dumper;


print Dumper(@ARGV);

my($config);

$config = &configure(scalar @ARGV);

sub configure{
    my $args = shift;
    my $config = {};
    my @current_samples = ();
    #my @old_samples = ();
    $config = {'current_samples' => \@current_samples};
    #$config = {'old_samples' => \@old_samples};
    GetOptions($config, 
           #"old_samples=s{,}",
           "current_samples=s{,}",
               "help|h!", )
        || warn "error : $!\n";
    print Dumper($config);
    return($config);
}

I can happily pass one file list and have it stored as expected:

[sb2 ~]$ perl test.pl -current_samples WS*
$VAR1 = '-current_samples';
$VAR2 = 'WS68726_1401';
$VAR3 = 'WS68726_1402';
$VAR4 = 'WS68726_1500';
$VAR5 = 'WS68726_1501';
$VAR1 = {
          'current_samples' => [
                                 'WS68726_1401',
                                 'WS68726_1402',
                                 'WS68726_1500',
                                 'WS68726_1501'
                               ]
        };

However, when I uncomment my second list parameter and use that my 'current_samples' variable is now a string with a single filename. Although the 'old_samples' variable has parsed correctly (as above):

[sb2 ~]$ perl test.pl -current_samples WS* -old_samples HG*
$VAR1 = '-current_samples';
$VAR2 = 'WS68726_1401';
$VAR3 = 'WS68726_1402';
$VAR4 = 'WS68726_1500';
$VAR5 = 'WS68726_1501';
$VAR6 = '-old_samples';
$VAR7 = 'HG001';
$VAR8 = 'HG002';
$VAR9 = 'HG003';
$VAR1 = {
          'current_samples' => 'WS68726_1501'
          'old_samples' => [
                             'HG001',
                             'HG002',
                             'HG003'
                           ]
        };

I tried swapping the order of variables around and the only one that made a difference was switching the config assignment ones:

sub configure{
    my $args = shift;
    my $config = {};
    my @current_samples = ();
    #my @old_samples = ();
    $config = {'current_samples' => \@current_samples};
    #$config = {'old_samples' => \@old_samples};
    GetOptions($config, 
           "current_samples=s{,}",
           "old_samples=s{,}",
               "help|h!", )
        || warn "error : $!\n";
    print Dumper($config);
    return($config);
}

Produces:

[sb2 ~]$ perl test.pl -current_samples WS* -old_samples HG*
$VAR1 = '-current_samples';
$VAR2 = 'WS68726_1401';
$VAR3 = 'WS68726_1402';
$VAR4 = 'WS68726_1500';
$VAR5 = 'WS68726_1501';
$VAR6 = '-old_samples';
$VAR7 = 'HG001';
$VAR8 = 'HG002';
$VAR9 = 'HG003';
$VAR1 = {
          'current_samples' => [
                                 'WS68726_1401',
                                 'WS68726_1402',
                                 'WS68726_1500',
                                 'WS68726_1501'
                               ],
          'old_samples' => 'HG003'
        };

I can't see anything in the GetOptions CPAN page which alludes to this ordering affect so any help would be greatly appreciated!

toolic
  • 57,801
  • 17
  • 75
  • 117
s_boardman
  • 416
  • 3
  • 9
  • 27
  • You are passing the number of elements in `@ARGV` to your sub `configure` and assign it to `$args` but never use it. Why? – simbabque May 20 '15 at 15:14
  • @simbabque I pass my '$configure' hash around between subroutines so it will get used downstream in the process. – s_boardman May 20 '15 at 15:22
  • That doesn't answer my question. ;) Also, have you thought about using Moo(se)? =) – simbabque May 20 '15 at 15:24
  • @simbabque Ah I see what you mean now. I'm not 100% sure why this is done, its standard practice by my boss and I've been learning Perl by using various scripts of his as a starting point. I shall investigate thusly. Havdn't come across Moose before, will take a look. :) – s_boardman May 20 '15 at 15:27
  • No offense to your boss, but from personal experience I can tell you not to trust your company's codebase to learn from. If you want to learn from other people's code, read CPAN. While you're at reading up stuff, check what the `&` in front of your function call does and consider if that is really the behaviour you want. ;-) – simbabque May 20 '15 at 15:37

2 Answers2

2

From your commented code it looks like you are overwriting $config with these lines:

$config = {'current_samples' => \@current_samples};
#$config = {'old_samples' => \@old_samples};

Instead, do all config assignments in one line:

my $config = {
  'current_samples' => \@current_samples,
  'old_samples' => \@old_samples,
};

Or you can do them in single lines and assign to the keys of the hashref:

my $config = {};
$config->{'current_samples'} = \@current_samples;
$config->{'old_samples'} = \@old_samples;
simbabque
  • 53,749
  • 8
  • 73
  • 136
1

As a an alternative solution, Getopt::Declare has syntax to support loading arguments into array references as well:

use strict; 
use warnings; 

use Getopt::Declare;

my $args = Getopt::Declare->new(
   join( "\n",
      '[strict]',
      "-current-samples <files>... \t List of file names",
      "-old-samples     <files>... \t List of file names",
   )
) || exit(1);

the ... after each tag tells Getopt::Declare to gather arguments into an array reference.

Then you just specify multiple space-separated values on the command line:

perl test-getopt-declare.pl -current-samples a b c d e f -old-samples 1 2 3 4 5 6
Hunter McMillen
  • 59,865
  • 24
  • 119
  • 170