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

I noticed that after using "getopt" at the start of the code reduces $#argv to "0",as a result my below code fails,basically I want to check "if the option f exists then the $#ARGV needs to 7" and "if the option f does not exist the $#ARGV needs to be 5".I tried moving "getopt" code down but the option check fails.Can anyone let me know how can I achieve this?

use Getopt::Std; use Data::Dumper; #Getting the command-line options my %options=(); getopt("fdrv",\%options); #print Dumper( \%options ); #USAGE if (exists $options{f}) { if ($#ARGV !=7) { print "USAGE withouf option f"; } } if (not exists $options{f}) { if ($#ARGV !=5) { print "USAGE without option f"; } }

Replies are listed 'Best First'.
Re: How to use getopt and $#argv together?
by toolic (Bishop) on Mar 09, 2011 at 18:24 UTC
    getopt modifies the @ARGV array. Before you call getopt, you can store the number of original args passed to the script, then use the new variable instead of $#ARGV:
    use Getopt::Std; use Data::Dumper; my $arg_num = scalar @ARGV; #Getting the command-line options my %options = (); getopt( "fdrv", \%options ); if ( exists $options{f} ) { if ( $arg_num != 7 ) { print "USAGE withouf option f\n"; } } if ( not exists $options{f} ) { if ( $arg_num != 5 ) { print "USAGE without option f\n"; } }
Re: How to use getopt and $#argv together?
by dasgar (Priest) on Mar 09, 2011 at 18:31 UTC

    To do what you're describing, move the $#ARGV check to be before the call to getopt. (Or do something like what toolic suggested.)

    Personally, I use Getopt::Long instead of Getpopt::Std. What I typically will do if set default values for variables. For the options that I want to be "required" options, I just check to see if the corresponding variables still have the default values. That way I let Getopt::Long handle the options processing and I'm just adding checks to ensure that variables have the acceptable values before continuing on. It might not be the "best" or more effective approach, but it works. Just thought I'd share an alternative method for doing the same thing.

Re: How to use getopt and $#argv together?
by mpeever (Friar) on Mar 09, 2011 at 18:42 UTC

    I check for required flags like this:

    my @args; GetOptions ( 'h|help' => sub { $help ++ }, 'debug' => sub { $debug ++ }, 'c|confirm' => \$confirm, 'i|instance=s' => \$instance, 's|service=s' => \@services, 'o|operation=s' => \$operation, 'm|message=s' => \$message, 't|timeout=i' => \$timeout, 'u|owner=s' => \$owner, '<>' => sub { push (@args, @_) } ); pod2usage ( -verbose => $help ) if $help; pod2usage ( -verbose => 1 ) unless scalar @services; pod2usage ( -verbose => 1 ) unless $operation and $message and $owner;
    It seems to me what you're trying to do is handled much more clearly by assigning a variable based on a flag, then checking that variable's value.

    I find Pod::Usage http://perldoc.perl.org/Pod/Usage.html invaluable. And I always use Getopt::Long.

      Can someone explain what the below statements mean?I looked at the usage doc,quite confusing

      pod2usage ( -verbose => $help ) if $help; pod2usage ( -verbose => 1 ) unless scalar @services; pod2usage ( -verbose => 1 ) unless $operation and $message and $owner;

        Besides the lines above, i also invoke pod2usage if Getops returns an failure errorcode:

        GetOptions( \%options, 'server=s', 'date=s', 'man', 'help', 'alert!', 'debug+' ) || pod2usage(2);

        Every file should contain within it the documentation for that script, in POD format. Type perldoc perlpod into an xterm, or browse http://perldoc.perl.org/perlpod.html for details.

        On the one hand, it's unsophisticated. On the other hand, it asks a lot. But people wouldn't fill in more complicated formatting, and you need to provide certain information.

        My solution is to set up a template file, which has everything I need to start a new script. it contains a few things I frequently use but may not need. My boss likes to have the RCS keywords. The ## no critic is to make perlcritic not complain about that line.

        #!/ms/dist/perl5/bin/perl5.10 # A one-line description of what this script does. our ($VERSION) = '$Revision: #24 $ ' =~ m{ \$Revision: \s+ (\S+) }x; # +# no critic (InterpolationOfMetachars); use 5.010; use warnings; use strict; # # Last edited by: $Author$ # on: $Date$ # Filename: $Source$ # Revision: $Revision$ # # ID: $Id$ # Database # use English qw( -no_match_vars ); use Fatal qw( open close ); use Readonly; use DBI; use POSIX 'strftime'; use Getopt::Long; use Pod::Usage; # ==================================================================== +== # Configuration Section # # ==================================================================== +== # Subroutines # ###################################################################### +## # Usage : # Purpose : # Returns : # Parameters : # Throws : # Comments : # See Also : # # ==================================================================== +== # Main Processing Section # MAIN: { my %options; GetOptions( \%options, 'man', 'help', 'alert!', 'debug+' ) || pod2usage(2); pod2usage(1) if $options{'help'}; pod2usage( '-verbose' => 2 ) if $options{'man'}; } # ==================================================================== +== __END__ =head1 NAME <application name> - <One line description of application's purpose> =head1 VERSION This documentation refers to <application name> version $Id$ =head1 USAGE # Brief working invocation example(s) here showing the most common + usage(s) # This section will be as far as many users ever read # so make it as educational and exemplary as possible. =head1 REQUIRED ARGUMENTS A complete list of every argument that must appear on the command line +. when the application is invoked, explaining what each of them does, a +ny restrictions on where each one may appear (i.e. flags that must appear + before or after filenames), and how the various arguments and options may interact (e.g. mutual exclusions, required combinations, etc.) If all of the application's arguments are optional this section may be omitted entirely. =head1 OPTIONS A complete list of every available option with which the application can be invoked, explaining what each does, and listing any restriction +s, or interactions. If the application has no options this section may be omitted entirely +. NOTE: This section, and nothing more, is printed out for C<prog -help> +. =head1 DESCRIPTION A full description of the application and its features. May include numerous subsections (i.e. =head2, =head3, etc.) =head1 DIAGNOSTICS A list of every error and warning message that the application can gen +erate (even the ones that will "never happen"), with a full explanation of e +ach problem, one or more likely causes, and any suggested remedies. If the application generates exit status codes (e.g. under Unix) then list th +e exit status associated with each error. =head1 CONFIGURATION AND ENVIRONMENT A full explanation of any configuration system(s) used by the applicat +ion, including the names and locations of any configuration files, and the meaning of any environment variables or properties that can be set. Th +ese descriptions must also include details of any configuration language u +sed =head1 DEPENDENCIES =head1 INCOMPATIBILITIES =head1 BUGS AND LIMITATIONS =head1 AUTHOR <name> <long.email>@company.com <date> <dept> =cut # ==================================================================== +== # End of File # ==================================================================== +==

        As Occam said: Entia non sunt multiplicanda praeter necessitatem.

        The Pod::Usage module provides pod2usage, which parses the POD documentation in your program and generates a usage message from it.

        I have those lines in place to handle two different use cases. First, if you call this program (no, it's not a complete program, just a snippet of some production code) with a -h or --help, it will print a usage message and exit. This is standard across the code I've written at this job.

        Second, there are required fields that are being checked. If there is no value for any of those fields (@services, $operation, etc.) then we present a usage message and exit. pod2usage causes the program to exit, so it's an effective check of whether continuing is actually feasible.

        This implies that I keep up the POD on my programs. I consider POD necessary in production code, so that's a non-issue. Not that I've never violated that rule...

        If you call pod2usage with a higher -verbose value, it prints out more information. This allows me to provide more or less detail based on how many -h flags were handed into my program. A single one means a simple usage message, multiples produce something like a manpage.

Re: How to use getopt and $#argv together?
by ikegami (Patriarch) on Mar 09, 2011 at 21:04 UTC

    I noticed that after using "getopt" at the start of the code reduces $#argv to "0"

    It doesn't for me.

    $ perl -MGetopt::Std -E'getopt(\%opts); say 1+$#ARGV;' -- -f a b c d 3 $ perl -MGetopt::Std -E'say Getopt::Std->VERSION' 1.06

    I suspect that you misstated your problem, asking about the number of arguments or options when you meant to ask how to check what options were specified. We could be of better assistance if you told us what you are actually trying to do.

      That's because you pass in the opt variable, but don't define any options to search for.

      325$ perl -MGetopt::Std -E'getopt(\%opts); say "@ARGV";' -- -f a -d b +-r -v a -d b -r -v 326$ perl -MGetopt::Std -E'getopt("fdrv",\%opts); say "@ARGV";' -- -f +a -d b > 327$

      As Occam said: Entia non sunt multiplicanda praeter necessitatem.

        No, specifying the options doesn't change anything.

        $ perl -MGetopt::Std -E' getopt("fdrv",\%opts); say 1+$#ARGV; say "@ARGV"; ' -- -f a b c d 3 b c d

        The only thing you showed is that removing the arguments produces an empty @ARGV.