Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid errors with perl command line parameters and use strict

Why is it that my code is not working after I added use strict; use warnings;? Is there a way to make it work?

Previously, the working code is:

#!/usr/bin/perl -s
print "x: $x\n";
print "y: $y\n";

The command that I ran is perl -s test.pl -x="hello" -y="world". The output is:

x: hello
y: world

However, after I added use strict; use warnings;, I got the following errors:

Variable "$x" is not imported at test.pl line 4.
Variable "$y" is not imported at test.pl line 5.
Global symbol "$x" requires explicit package name at test.pl line 4.
Global symbol "$y" requires explicit package name at test.pl line 5.
Execution of test.pl aborted due to compilation errors.

I know I need to declare my $x and my $y to fix the 3rd and 4th error. But what does the first 2 errors mean and how do I overcome it?

like image 650
Sakura Avatar asked Mar 07 '12 03:03

Sakura


People also ask

What is use strict and use warnings in Perl?

Strict and Warning are probably the two most commonly used Perl pragmas, and are frequently used to catch “unsafe code.” When Perl is set up to use these pragmas, the Perl compiler will check for, issue warnings against, and disallow certain programming constructs and techniques.

What does use strict do in Perl?

The strict pragma disables certain Perl expressions that could behave unexpectedly or are difficult to debug, turning them into errors. The effect of this pragma is limited to the current file or scope block. If no import list is supplied, all possible restrictions are assumed.

How do you pass input parameters to a Perl script?

If you want to use the two arguments as input files, you can just pass them in and then use <> to read their contents. Alternatively, @ARGV is a special variable that contains all the command line arguments. $ARGV[0] is the first (ie. "string1" in your case) and $ARGV[1] is the second argument.

How do I suppress a warning in Perl?

Warnings can be disabled selectively by using 'no warning' pragma within a scope along with an argument list. If the argument list is not provided then this pragma will disable all the warnings within that scope. Example: Perl.


2 Answers

Actually, declaring these variables as lexical (my) variables will not help, because it's too "late": the -s switch will already have set them. It sets the global (package) variables (in your case, $main::x and $main::y, or — as a special shorthand — $::x and $::y). If you don't want to have to refer to them using their package-qualified names, then you can use an our declaration to indicate that the bare names $x and $y refer to the $x and $y in the current package:

our ($x, $y);
print "x: $x\n"; 
print "y: $y\n";

(Hat-tip to derobert for pointing out that you can use our for this.)

Alternatively, you can copy the global variables into identically-named lexical variables:

my ($x, $y) = ($::x, $::y);
print "x: $x\n";
print "y: $y\n";

This will take care of both sets of diagnostics.

like image 135
ruakh Avatar answered Nov 15 '22 16:11

ruakh


You are using a a rudimentary switch parser perl -s, which uses global variables. To make it work with use strict you need to refer to the globals: $main::x as ruakh pointed out.

But even so, lexical variables (declared with my) are preferable in just about all cases. Just do:

use strict;
use warnings;

my ($x, $y) = @ARGV;
print "x: $x\n";
print "y: $y\n";

And use with:

perl test.pl hello world

For a more detailed and switch like handling, check out the Getopt::Long module.

like image 27
TLP Avatar answered Nov 15 '22 15:11

TLP