syedtoah has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks,
when i use Getopt::Long in a perl file and call the perl file alone it works but if i call the perl file within a shell script passing all the command line options to the perl file they wont work..... down is the example code

use Getopt::Long; my %options; $ret=GetOptions( "i" => \$options{i}, "o=s" => \$options{o}, "p=s" => \$options{p}, "h" => \$options{h} ); if ( $ret=="" || exists $options{'h'} || !@ARGV) { print " \nCommand line options: -i interactive -o file give a file -h help -p value personal exit; } else { if (exists $options{i}) { print "i is enabled\n"; } if (exists $options{o}) { print "o is enabled file is $options{o}\n"; } if (exists $options{p}) { print "p is enabled value is $options{p}\n"; } }

now the line in shell script is

perl ex.pl $*

here $* has the command line arguments

if the ex.pl is run with perl on the shell prompt i get proper output. but when i run the shell script with the same command line arguments i dont get the desired output....is it the problem with "exists" or the getopts

Edited by davido: Moved from PerlMonks Discussion to Seekers of Perl Wisdom, and formatted with paragraph and code tags.

janitored by ybiC: Correct module typo in title and node contents, "getops:long", for better site search results

Replies are listed 'Best First'.
Re: problem with Getopt::Long
by etcshadow (Priest) on Aug 20, 2004 at 06:26 UTC
    Well, one problem is that you are first calling GetOptions, and then asking that @ARGV not be empty... however, the way that GetOptions works is to remove values from @ARGV. So if all that is contained in @ARGV are -options, then after GetOptions, they'll have all been removed from @ARGV, and @ARGV will be empty.

    Another problem (that isn't with your Getopt::Long), is with your shell scripting. If you want to pass all arguments through to a command in a shell script, it's done like:

    command "$@"
    rather than
    command $*
    The difference can be demonstrated if you just take this simple shell script (lets call it "test.sh"):
    #!/bin/sh perl -e "use Data::Dumper; print Dumper \@ARGV" $*
    and call it with some arguments that will demonstrate why this breaks:
    [sstone@ernie1 scratch]$ sh test.sh 1 2 "3 and more stuff" $VAR1 = [ 1, 2, 3, 'and', 'more', 'stuff' ]; [sstone@ernie1 scratch]$
    but if we change test.sh to:
    #!/bin/sh perl -e "use Data::Dumper; print Dumper \@ARGV" "$@"
    and run it the same way:
    [sstone@ernie1 scratch]$ sh test.sh 1 2 "3 and more stuff" $VAR1 = [ 1, 2, '3 and more stuff' ]; [sstone@ernie1 scratch]$
    The difference being that "$@" will preserve the arg list as a list, whereas $* will flatten it all into a string (basically just like join(" ",@ARGV)), and then split it on whitespace... so if you had args with whitespace in them it would get all messed up.

    At the very least, that's a couple of things that might be causing you problems.

    ------------ :Wq Not an editor command: Wq
      i did what u have mentioned in ur mail, i changed $* to $@ and the result is the same. and one more thing i forgot to meition, when i call the shell script giving command line arguments and pass them to the perl script i see all the command line arguments and options present in the perl command in the shell script, but the thing happening here is that the very first if loop as mentioned in the code ie if (exists $options{x}) { do some thing } is giving positive irrespective of the option passed.... what wud be the problem here
        hey i have got the solution. As i had guessed there was a problem with the "exists". In all the if conditions the exists key word has to be removed for it to work as expectedloops...........any way thanks for contribution.....
Re: problem with Getopt::Long
by Random_Walk (Prior) on Aug 20, 2004 at 08:30 UTC
    Hi syedtoah

    There are a couple of probs with the given code

    • There is a " missing from the help printage
    • Getopt eats up the values in @ARGV so it is alway empty
    • the exits test is always true as Getopt creates the hash keys
    here is a fixed version that should work as expected.
    #!/use/your/bin/perl -w use strict; unless (@ARGV) {&usage} use Getopt::Long; my %options; my $ret = GetOptions( "i" => \$options{i}, "o=s" => \$options{o}, "p=s" => \$options{p}, "h" => \$options{h} ); if ($ret eq "" || $options{'h'}) {&usage} if ($options{i}) { print "i is enabled\n"; } if ($options{o}) { print "o is enabled file is $options{o}\n"; } if ($options{p}) { print "p is enabled value is $options{p}\n"; } sub usage { print " \nCommand line options: -i interactive -o file give a file -h help -p value personal\n"; exit; }

    Update
    As Nkuvu points out Getopts only eats up the valid options from @ARGV, anything else will remain so the test for @ARGV will pass if there are any non-option values in the command line.
      Getopt eats up the values in @ARGV so it is alway empty

      Just to be nitpicky -- not quite. Getopt eats the options in @ARGV. Anything else will remain. Consider the following:

      #!/usr/bin/perl use Getopt::Long; GetOptions( "i" => \$options{i}, "o=s" => \$options{o}, "p=s" => \$options{p}, "h" => \$options{h} ); foreach $arg (@ARGV) { print "$arg is still in ARGV\n"; } foreach $opt (keys %options) { print "$opt is $options{$opt}\n" if $options{$opt}; }
      and note the output:
      nkuvu$ perl try.pl --i h --o=foo h is still in ARGV o is foo i is 1

      I have used this to check some command line inputs. Specifically, for most of my scripts anything specified on the command line should be an option. Anything after that is an error. So I'd use it sort of like:

      GetOptions( #whatever ); die "Gah! (with appropriate error message here)\n" if (@ARGV);
        You are of course correct, I was trying to keep my posting brief and typed the short version of what was in my head. Then using a set of test cases whith only valid command line switches never made me think about it again.

        Cheers,
        R.