Got error using LWP - perl

I was trying to use LWP in perl, and I followed the example given in the link:http://www.perl.com/pub/2002/08/20/perlandlwp.html,
But I got errors as such:
"www.google.com" is not exported by the LWP::Simple module
Can't continue after import errors at /System/Library/Perl/Extras/5.12/LWP/Simple.pm line 23
And here is my code:
#!/usr/bin/perl -w
use LWP::Simple
$url = 'www.google.com';
$content = get $url;
Am I doing something wrong here?

You need a semicolon after your use statement, and your URL needs to have a protocol specified.
#!/usr/bin/perl
use LWP::Simple;
use strict;
use warnings;
my $url = 'http://www.google.com';
my $content = get $url;

Yes. You missed the semicolon after use LWP::Simple.

Had you used strict it would have told you that you have to declare $url. But if you declared both variables, you would still have gotten the error you did.
So, it's not a simple case of USUW.
Because you didn't put a semi-colon after the import statement, perl is assigning the string 'www.google.com' to the autovariable $url. And then, as it is an expression that can be passed, it passes that value as an export arguments of LWP::Simple.
Modules expect that any values passed as arguments to its import process, are symbols that the module--or Exporter--knows how to export.
So it's telling you that the whatever that string that you passed in is, it's not something that the module exports.
So, you just have to get used to this type of message pointing out that something is wrong with your import statement.

Related

perl function definition fails with uninitialized value

My perl chops are a little stale so I'm probably missing something really obvious here, but I've added a small module to some older code CGI code to refactor common functions. Here is an excerpt of the module with the part that is giving me problems:
package Common;
use strict;
use warnings;
use base 'Exporter';
our #EXPORT_OK = (&fail_with_error);
sub fail_with_error {
my ($errmsg, $textcolor) = #_;
my $output = printf("<p><font color=\"%s\">ERROR: %s </font>/<p>", $textcolor, $errmsg);
print($output);
exit(1);
}
When I execute this module directly with perl Common.pm (or when I just import the function in test code, without even calling it) what I get is an uninitialized value error for $errmsg and $textcolor like this:
$ perl Common.pm
Use of uninitialized value $textcolor in printf at Common2.pm line 10.
Use of uninitialized value $errmsg in printf at Common2.pm line 10.
<p><font color="">ERROR: </font>/<p>1
It would seem that perl is giving the warning because it is executing the subroutine code literally, but the nature of a subroutine is that it is abstracted so different values can be passed in correct? It would stand to reason these shouldn't have to be populated to pass interpreter warnings, but nonetheless something is wrong.
I've searched around, but this error is very common because in most cases the variable really is uninitialized. I can't seem to find anything that applies to this type of case.
That's because you're accidentally populating #EXPORT_OK with a call to fail_with_error: &fail_with_error, instead of the function name. This calls fail_with_errors with the arguments populated from the current #_ which happens to be empty - so naturally both the variables are uninitialized (and also your function doesn't get exported). The correct assignment uses just the subroutine name:
our #EXPORT_OK = qw( fail_with_error );

Using a var to select a var in Perl

I thought you used to be able to do this in "strict" mode, but I may be remembering incorrectly. Is is possible for something like this to work...
use strict;
use warnings;
package SomePackage;
my $TargetPID="demo:5"; #using "our" also works, but not in strict mode
my $VarName="TargetPID";
print ${$VarName}; #works but not in strict or if the var is declared with "my"
exit;
The reason I'm interested is that I'm trying to select a variable based on a text flag in a text file and I'd like to read in the content of the text file into a hash, then substitute some identifier along the lines of "#TargetPID#" with the corresponding variable. Being also able to specify both a package and a variable (or constant) would be a nice tbonus.
I can't think of any advantage of doing it the way you are trying to over just using a hash:
use strict;
use warnings;
package SomePackage;
my %vars = ();
$vars{'TargetPID'}="demo:5";
my $VarName="TargetPID";
print $vars{$VarName};
exit;
If you really must use $TargetPID as a variable and not a member of a hash, you can use eval:
my $TargetPID = "demo:5";
my $VarName = '$TargetPID';
print eval $VarName;
Or, if for some reason you need the value of $VarName to be 'TargetPID' and not '$TargetPID', you can do print eval '$' . $VarName.
You can use the PadWalker module for this. From the documentation:
PadWalker is a module which allows you to inspect (and even change!)
lexical variables in any subroutine which called you. It will only
show those variables which are in scope at the point of the call.
In your case, you would need to use peek_my, which does what it says: it allows you to peek into variables declared by my in a given scope.
#!/usr/bin/perl
use warnings;
use strict;
package SomePackage;
use PadWalker qw/peek_my/;
my $TargetPID = "demo:5";
my $VarName = "TargetPID";
print ${peek_my(0)->{'$' . $VarName}}
The subroutine peek_my takes one argument, a level, which is the number of subroutine calls to go back on the stack. It then returns a hash map of all the lexical my variables that were in scope at the time of the given call. In your case, the variable you want is defined in the same scope as where it is needed, so you would pass in 0, to go back 0 subroutine calls. Then you pull out the data you need like any other hash ref.
Be careful though, from the documentation:
PadWalker is particularly useful for debugging (emphasis mine.) It's even used by
Perl's built-in debugger. (It can also be used for evil, of course.)
I wouldn't recommend using PadWalker directly in production code, but
it's your call. Some of the modules that use PadWalker internally are
certainly safe for and useful in production.

issue with creating perl script to imitate linux command "ifconfig"

I have an assignment in which I am to create a Perl script in Linux to imitate the command ifconfig. This command basically shows you information about your network interfaces. I have already created the program, but a few lines are giving me some issues, I would appreciate if anyone could correct the code for me. The errors I am getting says that $get_iface_data requires an explicit package name at line 8, however I do not know how to declare that.
#!/usr/bin/perl
use strict;
use warnings;
use Net::Int::Stats;
use Net::Ifconfig::Wrapper;
my $Iface = $ARGV[0];
my $rx_packets = $get_Iface_data->value($Iface, 'rx_packets');
my $Iface_Info = Net::Ifconfig::Wrapper::Ifconfig('list', '', '', '');
print "\tether ". $Iface_Info->{$Iface}{'ether'}."\n";
My assignment basically requires me to get an interface as input, and display the info about that interface, as the ifconfig command would do. I also used two packages, Net::Int::Stats and Net::Ifconfig::Wrapper. The only difference between my script and the ifconfig command is my script will require an interface as parameter
Well, where do you defined $get_Iface_data?
The $foo->bar is a method call syntax. This means that $foo is some sort of object and bar is a method that can be used on that object.
Do you understand Object Oriented Programming and how Perl uses it? Perl has an excellent tutorial to help you get started.
What it comes done to is that you can't use a particular method (think subroutine) except on an object of that class. From this snippet of code, and what your error states, you never defined $get_Iface_data, so you have to define it. In this case, you have to create the object:
my $get_Iface_data = Net::Int::Stats->new();
Now, you can use the various Net::Int::Stats methods on the %get_Iface_data object:
my $rx_packets = $get_Iface_data->value($Iface, 'rx_packets');
You are just missing the line where you create the Net::Int::Stats object:
#!/usr/bin/perl
use strict;
use warnings;
use Net::Int::Stats;
use Net::Ifconfig::Wrapper;
my $Iface = $ARGV[0];
my $get_Iface_data = Net::Int::Stats->new();
my $rx_packets = $get_Iface_data->value($Iface, 'rx_packets');
my $Iface_Info = Net::Ifconfig::Wrapper::Ifconfig('list', '', '', '');
print "\tether ". $Iface_Info->{$Iface}{'ether'}."\n";

How to print out package code?

I have some difficulties with perl script which have one module (.pm) encoded by custom function and before module is loaded into .cgi scrcript is always decoded.
I could even let it be as it is but currently I have to do several changes in subroutines which this module contains and since it is encoded I am helpless ;/
So far I've tried several ways i.e:
#!/usr/bin/perl
use strict;
use lib '.';
use ModuleX; ### This is encoded module which I need
use CGI::Carp qw(fatalsToBrowser);
Unfortunatelly $body returns only ";" as a result ;/ I hope that it is possible to get those method code, but I have no idea what else I could do.
Thanks for help.
Are you trying to deparse the new method in the ModuleX package? Then I believe that you want to say
my $body = $deparse->coderef2text(\&Modulex::new);

In Perl, how do I send CGI parameters on the command line?

Normally i get the data from a webpage but i want to send it from the command line to facilitate debugging.
To get the data i do something like:
my $query = new CGI;
my $username = $query->param("the_username");
this doesn't seem to work:
$ ./script.pl the_username=user1
EDIT:
Actually the above works. The if statement that checked $username was wrong (using == instead of eq).
As I found out long time ago, you can indeed pass query string parameters to a script using CGI.pm. I am not recommending this as a preferred debugging method (better to have replicable stuff saved in files which are then directed to the STDIN of the script), however, it does work:
#!/usr/bin/env perl
use warnings; use strict;
use CGI;
my $cgi = CGI->new;
my $param_name = 'the_username';
printf(
"The value of '%s' is '%s'.\n",
$param_name, $cgi->param($param_name)
);
Output:
$ ./t.pl the_username=yadayada
The value of 'the_username' is 'yadayada'.
CGI reads the variables from standard input.
See this part of the CGI.pm documentation:
http://search.cpan.org/dist/CGI/lib/CGI.pod#DEBUGGING