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

I finally got my script to work through .profile. However, it appears that my regular expression is not doing entirely what I think it should be. I expected it to dump if the user enters a value that is outside of a certain range. What seems to be happening is that the regex detects and works for single digits, but it does not catch anything more than a single digit. I have appended the script and the output below.

SCRIPT
#!/opt/perl5/bin/perl -w use strict; my @instances; my $i; my $selection = 0; my $j = 0; opendir OPHOME, "/opt/lnpsite" or die "Can't open /opt/lnpsite: $!\n"; my @files = sort(readdir(OPHOME)); foreach(@files){ if (m/(op|nm)\d{2}$/) { push(@instances, $_); } } my $length = scalar(@instances); while ($j != 1) { &chooser(); } $selection = $selection - 1; ## COMPLETELY UNNECESSARY DEBUGGING CODE ## ########################################### print "\nSELECTION IS: ",int($selection),".... LENGTH IS: $length\n"; print "j is: $j\n"; my $conn = "/opt/lnpsite/" . $instances[$selection] . "/scripts/setup_ +env"; symlink("$conn", ".setup_env"); open CHOSENENV, ">chosen_setup_env"; print CHOSENENV "$instances[$selection]"; close CHOSENENV; sub chooser() { $i = 1; print "\nAvailable Instances\n===================\n"; foreach(@instances) { print " $i. ",$_,"\n"; $i++; } print "\nSelect an instance and press enter: "; $selection = <>; chomp($selection); if ($selection !~ /[1-$length]/) { print "\nIncorrect selection. Try again.\n"; } elsif ($selection !~ m/\d?/) { print "\nIncorrect selection. Try again.\n"; } else { $j = 1; } }

OUTPUT
Available Instances =================== 1. nm00 2. nm01 3. nm02 4. nm09 5. nm70 Select an instance and press enter: 111 SELECTION IS: 110.... LENGTH IS: 5 j is: 1 Use of uninitialized value in concatenation (.) or string at ./opSet.p +l line 28, <> line 1. Use of uninitialized value in string at ./opSet.pl line 32, <> line 1.
Thanks to all who have helped so much in already with this.

Replies are listed 'Best First'.
Re: Regex not working?
by peschkaj (Pilgrim) on Aug 13, 2002 at 18:04 UTC
    I combined Zaxo's answer and dws's answer to get something that worked quite nicely for me, and avoided the ugly return from redo unless.

    #!/opt/perl5/bin/perl -w use strict; my @instances; my $i; my $selection = 0; my $j = 0; opendir OPHOME, "/opt/lnpsite" or die "Can't open /opt/lnpsite: $!\n"; my @files = sort(readdir(OPHOME)); closedir OPHOME; foreach(@files){ if (m/(op|nm)\d{2}$/) { push(@instances, $_); } } my $length = scalar(@instances); while ($j != 1) { &chooser( \@instances ); } open CHOSENENV, ">chosen_setup_env"; print CHOSENENV "$instances[$selection]"; close CHOSENENV; sub chooser { $i = 1; my ($arrayRef) = @_; print "\nAvailable Instances\n===================\n"; foreach(@$arrayRef) { print " $i. ",$_,"\n"; $i++; } print "\nSelect an instance and press enter: "; $selection = <>; chomp($selection); $selection -= 1; if ($selection < -1) { #!~ m/[1-$length]/) { print "\nIncorrect selection. Try again.\n"; } elsif ($selection > $length) { # !~ m/(\d{1})?/) { print "\nIncorrect selection. Try again.\n"; } else { $j = 1; } }
Re: Regex not working?
by Zaxo (Archbishop) on Aug 13, 2002 at 17:37 UTC

    Your chooser() verification is incorrect. Simpler to do a numeric range check:

    redo unless $selection > -1 and $selection < @instances;

    Your code would benefit from tightening the scope of lexical variables. $selection should be lexical within sub chooser, and a reference to the @instances array should be an argument to it.

    After Compline,
    Zaxo

Re: Regex not working?
by dws (Chancellor) on Aug 13, 2002 at 17:54 UTC
    Your problem is in chooser().   if ($selection !~ /[1-$length]/) { ... isn't doing what you expect. It will accept (or reject, though the effect is to accept) any string that includes at least one digit in the given range.