4

I have some code like the following:

if (not defined $id) {
    print "Enter ID number: ";
    chomp ($id = <STDIN>);
    exit 0 if ($id eq ""); # If empty string, exit.
}
if (not defined $name) {
    print "Enter name: ";
    chomp ($name = <STDIN>);
    exit 0 if ($name eq ""); # If empty string, exit.
}
if (not defined $class) {
    print "Enter class: ";
    chomp ($class = <STDIN>);
    exit 0 if ($class eq ""); # If empty string, exit.
}

I'd like to be able to potentially pass only some of them (e.g., name and class, but not ID), passing blanks for the unpassed ones, so I thought the following would work:

if (not defined $id || $id eq "") {
    print "Enter ID number: ";
    chomp ($id = <STDIN>);
    exit 0 if ($id eq ""); # If empty string, exit.
}

But it doesn't seem to work if I pass, e.g., the following:

perl "myperlroutine.pl" "" "Mickey Mouse" "Entry"

The command window (I'm running this on Windows) briefly appears and then immediately disappears.

Am I missing something obvious?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
roryhewitt
  • 4,097
  • 3
  • 27
  • 33
  • a blank is still defined. it's just blank. – Marc B Sep 03 '14 at 18:24
  • 1
    [ysth's answer](http://stackoverflow.com/a/25651344/176646) addresses the issue in your logic, but see [how can I concisely check if a $variable is defined and contains a non zero length string?](http://stackoverflow.com/questions/1480066/in-perl-how-can-i-concisely-check-if-a-variable-is-defined-and-contains-a-non) for an alternative solution. – ThisSuitIsBlackNot Sep 03 '14 at 18:50
  • thanks to all for the useful answers. Prize goes to @ysth. Dave Cross - if I was only able to change this, but it's already being called from a multitude of places anyway, and I have time only to make a quick fix :( – roryhewitt Sep 04 '14 at 19:25

4 Answers4

16

You are using the low precedence not where you should be using the high precedence !.

So you are saying:

if ( not( defined $id || $id eq "" ) )

which is like:

if ( ! defined $id && $id ne '' )

which is always false.

So do

if ( ! defined $id || $id eq '' )

instead.

With Perl 5.12 and later, length() no longer warns when passed undef, which is incredibly convenient. So you can do simply:

if ( ! length $id ) {

which is short code, but it could be inefficient if $id could be a long UTF-8 string, where determining the length is hard. There I would be more inclined to do:

if ( ( $id // '' ) eq '' ) {

But that's not super readable unless you are familiar with that idiom.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ysth
  • 96,171
  • 6
  • 121
  • 214
4

You have received good answers explaining exactly what is wrong with your code. But no one has commented on the bigger picture.

Using positional arguments like this is (as you can see) problematic when the arguments become optional. In this situation, it's a far better idea to use named arguments. The standard Perl library comes with two modules (Getopt::Std and Getopt::Long) which make it easy to create flexible sets of command-line options. I recommend that you look at using one of those.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dave Cross
  • 68,119
  • 3
  • 51
  • 97
2

This pretty much covers anything you're looking for:

 if ( not length( $id )) { 
     ...
 }

AKA:

 unless ( length $id ) { 
     ...
 }
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Axeman
  • 29,660
  • 2
  • 47
  • 102
0

If your window is instantly disappearing that usually indicates a compilation error. You should open the command window and run the script from the command line:

  • Click "start"
  • type "cmd" into the search bar and hit Enter.

Then run your script from the command line as follows:

perl full_path_to_script\script_name.pl

If you do this, the command window should not instantly close. Instead, it should give some feedback on why your script is failing to run. If you still can't figure out why it is failing after doing that, you should post your compilation errors as well and we can take a look at them.

Also, ysth is correct. You should be using "!" instead of "not".

Example:

if ((!defined $id) || ($id eq '')) {
    print "Enter ID number: ";
    chomp ($id = <STDIN>);
    exit 0 if ($id eq ""); # If empty string, exit.
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
tjwrona1992
  • 8,614
  • 8
  • 35
  • 98