http://www.perlmonks.org?node_id=827603

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

What I am trying to do is ask the user where the file lives, grab the group file, send each cell name in the file to run the.tcl script and if they add a -s or -d switch to the end of the file line the script will run with those switches. When I run the script I get this error message
Global symbol "$opt_s" requires explicit package name at runrv1271.pl line 5. Global symbol "$opt_d" requires explicit package name at runrv1271.pl line 6. BEGIN not safe after errors--compilation aborted at runrv1271.pl line 8.

#!/usr/local/bin/perl -w
#This script will allow the user to run a group of cells using a group file through the .tcl script.

$s = "-use_slopefile 1";
$d = "-dcc 1";

use Getopt::Long;

$groupDir = &promptUser("Enter the entire directory path to your group file.");

GetOptions ('file=s' => \$groupDir,
's=s' => \$s,
'd=s' => \$d);

print "$groupDir\n";

sub promptUser {
my($prompt, $default) = @_;
my $defaultValue = $default ? "$default" : "";
print "$prompt $defaultValue: ";
chomp($input = <STDIN>);
return $input ? $input : $default;
}

open(USERINPUT, "<$groupDir") || die "Sorry, I could not find a group file by that name here. $!\n";

foreach $cell (<USERINPUT>){
chomp $cell;
$ENV{`CLD_RV/rv_char.tcl -cell $cell`);

}
close(USERINPUT);

Replies are listed 'Best First'.
Re: How to use getopts?
by bv (Friar) on Mar 09, 2010 at 19:25 UTC

    Your code has some other issues, which I'll get to in a bit, but regarding Getopt, here are some ideas:

    1. Call GetOptions early, so that you can validate inputs. You are prompting for input even when the user provides groupDir as an argument. Instead, call GetOptions and then prompt if $groupDir is not set.

    2. Check for failure of GetOptions in case the user provided an incorrect option. This is easiest like this: GetOptions('slopefile=s' => \$s) or die "Invalid option";

    3. Take advantage of the Long part of Getopt::Long and use long option names. It won't prevent the user from using something like -s if they want to, but it makes your code (and your documentation) more readable to allow -slopefile.

    Lastly, a few words about your code in general. You should always use strict; use warnings;. Use the 3-argument form of open, with lexical (my) filehandles, and use or, not || for or die error checking. This would change your code to look like this:

    open my $userinput, '<', $groupDir or die "Error opening $groupDir: $!";

    Your use of the ternary operator (?:)could be changed to the more straightforward defined-or assignment operator, //=. If you have an older version of perl than 5.10.0, logical-or ||= may work in most cases, but may cause bugs in others.

    Best of luck with your program!


    print map{substr'hark, suPerJacent other l',$_,1}(11,7,6,16,5,1,15,18..23,8..10,24,17,0,12,13,3,14,2,4);
Re: How to use getopts?
by toolic (Bishop) on Mar 09, 2010 at 18:51 UTC
Re: How to use getopts?
by ssandv (Hermit) on Mar 09, 2010 at 19:03 UTC

    A couple quick housekeeping things first: There are instructions on formatting your posts immediately below the posting box, and it helps us a lot to help you if you follow them. In particular, <code></code> tags around your code fragment make it easier to read, prevent brackets from being treated as markup, and give us a "download" button which pops the code up in a new page without any inconvenient line wrapping. Also, you'll want to get in the habit of useing strict as well as warnings (you're already using warnings, since you have the -w option in your shebang line, so that's good!).

    You ask if you are on the right track, but it's far more effective if you tell us what you've seen happen so far. Have you run the code? If not, why not? If so, what did you see? One thing that seems odd to me is that you allow the user to enter the file on the command line, but then still prompt them for a filename even if they give one on the command line. Another problem is that you're using the wrong version of or to do your open ... or die (you want or which has the lowest precedence, not ||, which has a higher one). I also don't see where you ever construct the tcl command itself, so it's hard to know if you're "on the right track"

    There are a number of other technical quibbles with your Perl style which you may or may not be interested in (it looks like you're using some style elements that were once standard or even necessary, but are now deprecated). Unless you're stuck using a very old version of Perl, you can use scalar variables for your filehandles instead of barewords (e.g. USERINPUT), and this has a lot of advantages. Also, the 3-argument form of open is better than the 2-argument form (among other things, it helps in the case where the filename includes strange characters). There's other stuff too, but that's a good start for now.

    In short, don't post a really short problem statement with a bunch of code and ask how you're doing. Post code (in appropriate tags), post the results you got from running it, or a clear statement of where you're stuck, and describe in detail what you thought it should do or don't understand why it did.

Re: How to use getopts?
by ikegami (Patriarch) on Mar 10, 2010 at 23:43 UTC

    First you input $groupDir from STDIN, then you replace it with that was previously supplied on the command line. That doesn't make any sense. Do you want to the caller to provide it via STDIN or via command line? (I'd pick the latter.)

    the script will run with those switches.

    Presumably this this the line that launches the script.

    $ENV{`CLD_RV/rv_char.tcl -cell $cell`);

    Aside that it's mostly nonsense, You seem to forgot to pass the switches.

    Global symbol "$opt_d" requires explicit package name

    uh, that error doesn't come from the code you posted.