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?
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.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With