Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

More on Processing Command Line Arguments

by Ninthwave (Chaplain)
on Oct 31, 2003 at 15:55 UTC ( [id://303577]=perlquestion: print w/replies, xml ) Need Help??

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

I have discussed command line argument processing before. And was given some great code. Now at this point I want to have a script that can be called with options to either add a record, edit a record, list all records or view a record. But you should only enter one choice. This seems to be working for me. For people with more experience with GetOpt::Long is there a better way to do this. I know better is subjective but I like comparing other ways to my ways so I can break any bad habits I may be forming. My main query is should I do the long xor statement check, is that check adequate and am I missing something in Getop::Long that marks entries as being required or selective.

use strict; use Getopt::Long; use Pod::Usage; #******************************************************** #** Intialise variables #******************************************************** my $Add_Record= 0; my $Edit_Record= 0; my $List_Records = 0; my $View_Record = 0; my $Manual = 0; my $Help = 0; #******************************************************** #** Process command line arguments. #******************************************************** GetOptions( 'add|a=s' =>\$Add_Record, 'edit|e=s' =>\$Edit_Record, 'list|l=s' =>\$List_Records, 'view|v=s' =>\$View_Record, 'man|m' =>\$Manual, 'help|h|?' =>\$Help ); #******************************************************** #** Print Usage files based on the status of the command #** line arguments. #******************************************************** pod2usage(1) if $Help; pod2usage(-exitstatus => 0, -verbose => 2) if $Manual; if (($Add_Record xor $Edit_Record) xor ($List_Records xor $View_Record +)) { # Run Program } else { # Print manual }
Update:Moved intialise variables to the proper place in the code, bad editting by me. This is how the code looks that I am testing. Noting that if three options are choosen the if statement returns true.

Replies are listed 'Best First'.
Re: More on Processing Command Line Arguments
by Ovid (Cardinal) on Oct 31, 2003 at 16:50 UTC

    And a quick cleanup:

    #!/usr/bin/perl use warnings; use strict; use Getopt::Long; use Pod::Usage; #******************************************************** #** Process command line arguments. #******************************************************** GetOptions( 'add=s' =>\my $Add_Record, 'edit=s' =>\my $Edit_Record, 'list=s' =>\my $List_Records, 'view=s' =>\my $View_Record, 'man' => sub {pod2usage({-verbose => 2, -input => \*DATA})}, 'help|?' => sub {pod2usage({-verbose => 1, -input => \*DATA})}, ); if (($Add_Record xor $Edit_Record) xor ($List_Records xor $View_Record +)) { # Run Program } else { # Print manual } __END__ =head1 NAME somescript -- A utility for ... =head1 SYNOPSIS B<somescript --help> for more information somescript [options] Options:

    Note a few things.

    • First, the short forms of the options are automatically available. You don't need to add them.
    • Taking a reference to a variable when you declare it is a nice shorthand.
    • I have pod2usage take __DATA__ as the input because I've had problems with this working when I do funky things with directories.

    Cheers,
    Ovid

    New address of my CGI Course.

      Thank you it is much cleaner but I still can't get that if statement to work. I will get it just need to sketch it out right.

        You know, I saw your script and immediately thought about cleaning it up. I didn't even think about reading your question :)

        A simple way of ensuring that only one option is used at a time:

        GetOptions( 'add=s' =>\my $add, 'edit=s' =>\my $edit, 'list=s' =>\my $list, 'view=s' =>\my $view, 'man' => sub {pod2usage({-verbose => 2, -input => \*DATA}); exi +t}, 'help|?' => sub {pod2usage({-verbose => 1, -input => \*DATA}); exi +t}, ); if (1 == grep { defined } ( $add, $edit, $list, $view )) { print "Good!"; } else { print "Bad!\n"; }

        Cheers,
        Ovid

        New address of my CGI Course.

Re: More on Processing Command Line Arguments
by ctilmes (Vicar) on Oct 31, 2003 at 16:01 UTC
    Two comments:

    1) Move your "initialize variables" section above your call to GetOptions so the lexical variables will exist before you use them.

    2) pod2usage() will exit your program, so you don't need the "print manual" in the else.

      Sorry that was a cut and paste error when I first copied it I chopped off the initialisation of the variables, when I pasted them pack in I did it in the wrong place. I have found I flaw in the logic also while testing, and am focussing on getting it so that only one of the four options is specified for add record, edit record, list records, view record. the line

      if (($Add_Record xor $Edit_Record) xor ($List_Records xor $View_Record +))
      is not the logic I want. In that case if three values are true the statement is true.

Re: More on Processing Command Line Arguments
by Abigail-II (Bishop) on Oct 31, 2003 at 16:21 UTC
    am I missing something in Getop::Long that marks entries as being required or selective
    You aren't. As Johan (author of Getopt::Long) likes to say: when arguments are required, they aren't options.

    Abigail

      Is there a better method for doing this. Should I make the program interactive with a menu instead. I lean towards options because they can be scripted themselves. So I could use the above code script.pl -v record_ID >output.txt or script.pl -a <input.txt

      Though I would have to change a because right now it requires a parameter passed to it and it really shouldn't

        When I want to make arguments required, I use Getopt::Long, and just put in an additional check for the 'option' that I want to be required.

        Abigail

(shockme) Re: More on Processing Command Line Arguments
by shockme (Chaplain) on Oct 31, 2003 at 16:22 UTC
    If you're wanting to ensure they only use one option, it seems the easiest would be to only allow one option. For example:
    GetOptions( 'request|r=s' =>\$Request, 'man|m' =>\$Manual, 'help|h|?' =>\$Help ); if ($Request =~ /^list$/i) { # whatever } elsif ($Request =~ /^view$/i) { # whatever } # and so on

    But I may be misunderstanding the issue. Not an uncommon event in my life.

    If things get any worse, I'll have to ask you to stop helping me.

      What the script does is:

      1. Add a record to a database
      2. Edit a record from a database
      3. List the records in the database
      4. View a record from a database

      But you should only be able to do one option at a time. I would like to call that in the command line instead of having a menu system in the script itself.

Re: More on Processing Command Line Arguments
by TomDLux (Vicar) on Oct 31, 2003 at 18:28 UTC
    Instead of the XOR, you could simply ensure that only one of the options is activated. Of course if more than one is selected in the command line arguments, the order of processing selects one by default. In some cases, ignoring user errors can be risky, but often, an appropriate order will simply result in some superfluous data output.

    if ( $Add_Record ) { Add_Record( $args ); elsif ( $Edit_Record ) { Edit_Record( $args ); elsif ( $List_Records ) { List_Records( $args ); elsif ( $View_Record ) { View_Record( $args ); else { pod2usage(-verbose => 1); } __END__

    --
    TTTATCGGTCGTTATATAGATGTTTGCA

Re: More on Processing Command Line Arguments
by bbfu (Curate) on Oct 31, 2003 at 18:57 UTC

    How about something like this:

    #!/usr/bin/perl use warnings; use strict; use Getopt::Long; use Pod::Usage; my $Action; # Will be one of: add, edit, list, view my $Value; # Will be the value of the =s part of the option sub set_action { pod2usage( -message => 'Must use only one of --add, --edit, --list, or --view +', ) if defined $Action; $Action = shift; $Value = shift; } GetOptions( 'add|a=s' => \&set_action, 'edit|e=s' => \&set_action, 'list|l=s' => \&set_action, 'view|v=s' => \&set_action, 'man|m' => sub { pod2usage(-exitstatus => 0, -verbose => 2) }, 'help|h|?' => sub { pod2usage(1) }, ) or pod2usage(2); # Update2: Changed back to pod2usage(2) from exit(2) (see below) pod2usage( -message => 'Must use at least one of --add, --edit, --list, or --vi +ew', -exitval => 1, ) unless defined $Action; # Run program { add => \&add_record, edit => \&edit_record, list => \&list_record, view => \&view_record, }->{$Action}->($Value); sub add_record { my $record = shift; print "Adding record $record.\n"; } sub edit_record { my $record = shift; print "Editing record $record.\n"; } sub list_record { my $record = shift; print "Listing record $record.\n"; } sub view_record { my $record = shift; print "Viewing record $record.\n"; } =head1 NAME Program Name - description =head1 SYNOPSIS program [--man] [--help] --add|--edit|--list|--view RECORD -a, --add RECORD Add a record -e, --edit RECORD Edit a record -l, --list RECORD List record(s) -v, --view RECORD View a record -h, -?, --help Display this help screen -m, --man Display the program's manual Note, you must include one (and only one) of add, edit, list, or view. =head1 DESCRIPTION Detailed program description. =head1 AUTHOR The Author =cut

    When I tested this, the pod2usage stuff didn't work at all. I think, however, it's an issue with my installation of Pod::Usage, and the option-related part of this code does work so I am posting it anyway. If you also have a problem with pod2usage not working with this, or similar, code, let me know so I can try to determine where the issue lies.

    Update: Made a minor update to the code. Noted in comment.

    Update2: Ok, my problems with pod2usage are definately just an issue with my cygwin install of Pod::Usage. I tested the above code with my ActivePerl install, and it works fine. Also, I was mistaken about GetOptions not allowing pod2usage to die properly, so I changed the code back.

    bbfu
    Black flowers blossom
    Fearless on my breath

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://303577]
Approved by gjb
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (4)
As of 2024-03-29 15:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found