in reply to Usage of flags in scripts

Well, I believe everyone will recommend you use a module to do this. I suggest using either getopt::long or getopt::simple.

#!/usr/bin/perl use warnings; use strict; use Getopt::Long; use 5.010; # Just to use say() my ($mean, $sum); my $result = GetOptions ("mean" => \$mean); my @nums = @ARGV; foreach (@nums) { say; # Only calculate the mean if flag exists if ($mean) { $sum += $_; } } say $sum/@nums if $mean; __END__ $ perl mean.pl 1 3 2 1 3 2 $ perl mean.pl -m 1 3 2 1 3 2 2 $ perl mean.pl -mean 1 3 2 1 3 2 2

Notice how Getopt::Long allows the user to type just enough of the switch to trigger it. If there was another switch called meek, the user would have to distinguish which switch they were triggering by typing either -mee (or -meek) or -mea (or -mean).

Updated with example.

And you didn't even know bears could type.

Replies are listed 'Best First'.
Re^2: Usage of flags in scripts
by Your Mother (Archbishop) on Jan 01, 2009 at 00:03 UTC

    Or you could-

    #!/usr/bin/perl -l

    -instead of-

    use 5.010; # Just to use say()

    To get print to act like say which is a bit more on point for the OP. :)

      or even...
      sub say { # Perl Hacks #86 print @_, "\n"; }
        Except that this doesn't handle saying to filehandles properly:
        $ perl -e 'sub say { print @_, "\n" } say STDOUT "Hi"' Can't locate object method "say" via package "IO::Handle" at -e line 1

      Haha, that is neat. I need to reread perlrun more often ;)

      And you didn't even know bears could type.

Re^2: Usage of flags in scripts
by jordandanford (Initiate) on Jan 01, 2009 at 01:24 UTC

    Great, thank you! One more question, though - is there a way I can stop Getopt::Long from parsing negative number arguments as flags?
    For example, if my data set is (12, 5, 7, 1, -3), -3 is parsed as as a flag, not a numerical argument

      After reading the documentation, I believe this can be done by changing use Getopt::Long; to use Getopt::Long qw(:config require_order);.

      require_order

      Whether command line arguments are allowed to be mixed with options. Default is disabled unless environment variable POSIXLY_CORRECT has been set, in which case require_order is enabled.

      See also permute, which is the opposite of require_order.

      Getopt::Long will stop processing flags and such once it sees an argument without a dash.

      And you didn't even know bears could type.

        This runs into a problem if the negative number is the first argument, since Getopt::Long then has no way to know that it's not a genuine flag. The solution is the usual GNU-style -- flag, which signals the end of options (so that require_order isn't even necessary, though it'll do no harm—besides being more natural, I think).

        Great, thank you!

      These various getopt things parse tokens on the command line.

      In your case, perhaps Getopt::Std will be just fine. This not to say that that other suggestions aren't fine also.

      use Getopt::Std; my %opts; die "Usage $0 -m or -M #1 #2 #3..." if (!getopts( "mM", \%opts) || @ARGV !=0 || keys %opts != 2); CalculateMean() if $opts{m}; #@ARGV has just #1 #2 #3 ...now. CalculateMedian() if $opts{M};

      getopts::Std take a string and a ref to a hash as args. The magic of getopts in its various flavors is that it removes the option and the parameter (if any) from @ARGV.

      There is a syntax for this: "mf:" means that "-m" doesn't have an arg, but that "-f" does, like someprogram -m -f filename 1 2 3. In this case the %opts hash will have keys of "m" and "f". The value of $opts{m}=1, the value of $opts{f} = 'filename' and @ARGV = (1,2,3).

      You can have things like -a -f filename 1 2 3 4 or -f filename -a 1 2 3 4. Of course if somebody types in: -a -f 1 2 3 4 filename, you have to figure out that "1" isn't a filename. Anyway getopts looks for essentially space separated tokens, -3 like +3. That's the way that a C program would get the args.

      I hope this helped.

        Sorry there is an extra paren in the code. Don't know how to edit this out yet. corrected now.