Why the following code shows an error? - perl

I want to pass arguments from the command line so i had tried the following code but it throws an error?
use strict;
use warnings;
use Getopt::Long qw(GetOptions);
use Getopt::Std;
print "raw data:#ARGV\n";
my $site=getopts('bangalore','norwood','limerick');
if($site)
{
print "success";
}
else
{
die "error";
}
print "final data:#ARGV \n";

Your code is not correct. Please go through the documentation first: http://perldoc.perl.org/Getopt/Long.html
Below is an attempt to guess what you were trying to achieve.
use strict;
use warnings;
use Getopt::Long qw(GetOptions);
my $city;
print "raw data:#ARGV\n";
GetOptions ("city=s" => \$city) or die("Error in command line arguments\n");
my $site = $city;
if($site){
print "success: City is $city\n";
}
print "Final data:#ARGV \n";
Output:
chankeypathak#stackoverflow:~/Desktop$ perl test.pl -city=bangalore
raw data:-city=bangalore
success: City is bangalore
Final data:
Output when passed incorrect param:
chankeypathak#stackoverflow:~/Desktop$ perl test.pl -blah=blah
raw data:-blah=blah
Unknown option: blah
Error in command line arguments

Thanks to: alvinalexander
#!/usr/bin/perl -w
# a perl getopts example
# alvin alexander, http://www.devdaily.com
use strict;
use Getopt::Std;
# declare the perl command line flags/options we want to allow
my %options=();
getopts("hj:ln:s:", \%options);
# test for the existence of the options on the command line.
# in a normal program you'd do more than just print these.
print "-h $options{h}\n" if defined $options{h};
print "-j $options{j}\n" if defined $options{j};
print "-l $options{l}\n" if defined $options{l};
print "-n $options{n}\n" if defined $options{n};
print "-s $options{s}\n" if defined $options{s};
# other things found on the command line
print "Other things found on the command line:\n" if $ARGV[0];
foreach (#ARGV)
{
print "$_\n";
}

Related

How to use GetOptions to detect trailing strings?

I am absolutely new to Perl and I am trying to figure out a problem with Perl script parsing script arguments.
I have the following Perl script called sample-perl.pl:
use strict;
use warnings;
use 5.010;
use Getopt::Long qw(GetOptions);
my $source_address;
my $dest_address;
GetOptions('from=s' => \$source_address,
'to=s' => \$dest_address) or die "Usage: $0 --from NAME --to NAME\n";
if ($source_address) {
say $source_address;
}
if ($dest_address) {
say $dest_address;
}
And if I use a command like (where I forgot to enter the second option):
perl sample-perl.pl --from nyc lon
Output will be: nyc
How can I enforce that if there is an additional string at the end, it is detected and an error is displayed instead?
Solution:
adding this will help my case at least:
if(#ARGV){
//throw error
}
After calling GetOptions, check for any remaining command line options in the #ARGV array. This assumes that all unexpected arguments will generate an error:
use strict;
use warnings;
use 5.010;
use Getopt::Long qw(GetOptions);
my $source_address;
my $dest_address;
GetOptions('from=s' => \$source_address,
'to=s' => \$dest_address) or die "Usage: $0 --from NAME --to NAME\n";
#ARGV and die "Error: unexpected args: #ARGV";
if ($source_address) {
say $source_address;
}
if ($dest_address) {
say $dest_address;
}
I was busy answered and I see it is now answered, just some additional info.
use strict;
use warnings;
use 5.010;
use Getopt::Long qw(GetOptions);
my $source_address;
my $dest_address;
GetOptions('from=s' => \$source_address,
'to=s' => \$dest_address) or die "Usage: $0 --from NAME --to NAME\n";
#ARGV and die "To many arguments after --from or --to : #ARGV ";
if ($source_address) {
say $source_address;
} else {
say "Error: No Source specified"; #Check to see if --from is actually specified, else print error.
}
if ($dest_address) {
say $dest_address;
} else {
say "Error: No destination specified"; #Check to see if --to is actually specified, else print error.
}
so in short

Functional interface to IO::Compress::Gzip is not handling arguments correctly

Here is a simple example to illustrate the issue I am seeing when trying to use IO::Compress::Gzip:
use strict;
use warnings;
eval {
require IO::Compress::Gzip;
IO::Compress::Gzip->import();
1;
} or do {
my $error = $#;
die "\nERROR: Couldn't load IO::Compress::Gzip" if $error;
};
my $input = shift;
my $out = $input.".gz";
print "Defined!\n" if defined $out;
IO::Compress::Gzip::gzip $input => $out
or die "gzip failed: $!\n";
This generates the following error:
Defined!
Use of uninitialized value $_[1] in string eq at /home/statonse/perl/perlbrew/perls/perl-5.22.0/lib/5.22.0/IO/Compress/Base/Common.pm line 280.
IO::Compress::Gzip::gzip: output filename is undef or null string at test.pl line 17.
However, if I use the object interface:
use strict;
use warnings;
eval {
require IO::Compress::Gzip;
IO::Compress::Gzip->import();
1;
} or do {
my $error = $#;
die "\nERROR: Couldn't load IO::Compress::Gzip" if $error;
};
my $input = shift;
my $out = $input.".gz";
print "Defined!\n" if defined $out;
my $z = new IO::Compress::Gzip $out
or die "IO::Compress::Gzip failed: $!\n";
$z->print($input);
It works just fine. For some context, it would work as normal if I imported the module with use:
use strict;
use warnings;
use IO::Compress::Gzip;
my $input = shift;
my $out = $input.".gz";
IO::Compress::Gzip::gzip $input => $out
or die "gzip failed: $!\n";
but I am trying to avoid that since this library is rarely used in the application. Is there something obvious I am doing wrong or is this a behavior specific to this module?
This line:
IO::Compress::Gzip::gzip $input => $out
is parsed differently depending on whether the parser knows that there is a function called IO::Compress::Gzip::gzip or not.
When you load the library with use, its functions are known to the parser before the rest of your program is parsed (because use is a type of BEGIN). In this case the parser chooses the interpretation you want.
In the other case, it chooses the alternate interpretation: indirect object syntax, equivalent to $input->IO::Compress::Gzip::gzip, $out
You can see this for yourself by running perl -MO=Deparse on the different versions of your program.
The fix is to make the function call explicit with parentheses:
IO::Compress::Gzip::gzip($input, $out)
The parser can't misinterpret that.

Whole string not getting read while reading the file using Config::IniFiles

I am unable to print the whole lines as i try and parse the ini file using Config:Ini operation, its the last part where I believed that the array will have the whole line and not only the key, I am surely missing something here
Input
[DomainCredentials]
broker=SERVER
domain=CUSTOMER1
[ProviderCredentials]
Class=A
Routine=B
Code
#!/sbin/perl -w
use lib "/usr/lib/perl5/site_perl";
use lib "/usr/lib/perl5/vendor_perl";
use strict;
use warnings;
use Config::IniFiles;
my $sPPFile="/tmp/config.txt";
my $sysSec="DomainCredentials";
my $cfg = Config::IniFiles->new(-file=> $sPPFile) || die "Could open file $sPPFile\n";
if ($#){
print "Error";
exit 1;
}
my #params_provider = $cfg->Parameters("ProviderCredentials");
foreach (#params_provider){
print $_."\n";
}
Output
Class
Routine
Expected Output
Class=A
Routine=B
You could use the tied hash option of Config::IniFiles to get the config.txt parameter/value pairs:
use strict;
use warnings;
use Config::IniFiles;
my %ini;
my $sPPFile = "/tmp/config.txt";
tie %ini, 'Config::IniFiles', ( -file => $sPPFile );
print "$_=$ini{ProviderCredentials}{$_}\n"
for keys %{ $ini{ProviderCredentials} };
Output on your dataset:
Class=A
Routine=B
You can change the value of a parameter, and then update the config file by doing this:
$ini{ProviderCredentials}{Class} = 'C';
tied(%ini)->RewriteConfig();
The last command actually writes out the entire config held in the tied hash.
Hope this helps!
It looks like Parameters only returns keys.
You then have to use val to get the values.
#!/sbin/perl -w
use lib "/usr/lib/perl5/site_perl";
use lib "/usr/lib/perl5/vendor_perl";
use strict;
use warnings;
use Config::IniFiles;
my $sPPFile="/tmp/config.txt";
my $sysSec="DomainCredentials";
my $cfg = Config::IniFiles->new(-file=> $sPPFile) || die "Could open file $sPPFile\n";
if ($#){
print "Error";
exit 1;
}
my #param_arr = ('broker','domain');
my %param_hash;
foreach my $p (#param_arr){
if (defined $cfg->val("$sysSec",$p)){
$param_hash{$p} = $cfg->val("$sysSec",$p);
}
else{
die "Could not get parameter $p\n";
}
}
#print $param_hash{broker};
#print $param_hash{domain};
my #params_provider = $cfg->Parameters("ProviderCredentials");
if (defined $cfg->Parameters("ProviderCredentials")){
my #params_provider = $cfg->Parameters("ProviderCredentials");
}else{
die "Could not get parameter ProviderCredentials\n";
}
foreach (#params_provider){
print "Key : ".$_."\t Value : ".$cfg->val("ProviderCredentials",$_)."\n";
}

Devel::Declare removes line from script

I am trying to learn Devel::Declare so as to attempt to reimplement something like PDL::NiceSlice without source filters. I was getting somewhere when I noticed that it was removing the next line from my script. To illustrate I have made this minimal example wherein one can use the comment keyword to remove the entire line from the code, allowing a compile even though barewords abound on that line.
#Comment.pm
package Comment;
use strict;
use warnings;
use Devel::Declare ();
sub import {
my $class = shift;
my $caller = caller;
Devel::Declare->setup_for(
$caller,
{ comment => { const => \&parser } }
);
no strict 'refs';
*{$caller.'::comment'} = sub {};
}
sub parser {
#my $linestr = Devel::Declare::get_linestr;
#print $linestr;
Devel::Declare::set_linestr("");
}
1
and
#!/usr/bin/env perl
#test.pl
use strict;
use warnings;
use Comment;
comment stuff;
print "Print 1\n";
print "Print 2\n";
yields only
Print 2
what am I missing?
P.S. I will probably have a few more questions on D::D coming up if I should figure this one out, so thanks in advance!
Ok so I got it. Using perl -MO=Deparse test.pl you get:
use Comment;
use warnings;
use strict 'refs';
comment("Print 1\n");
print "Print 2\n";
test.pl syntax OK
which tells me that if forces the comment function to be called. After some experimentation I found that I could just set the output to call comment() explicitly so that it doesn't try to call comment on whatever is next.
sub parser {
Devel::Declare::set_linestr("comment();");
}
so that the deparse is:
use Comment;
use warnings;
use strict 'refs';
comment();
print "Print 1\n";
print "Print 2\n";
test.pl syntax OK
and the proper output too.

Is it possible to get the variable defined in the perl file to the pm file?

test.pm
package test;
use Exporter;
our #ISA=qw(Exporter);
#EXPORT=qw(version);
sub show(){
print $var;
}
sub version()
{
$out=`uname`;
return $out;
}
test.pl
#!/usr/bin/perl
BEGIN{
use lib qw(./Module);
}
use test;
our $var="what to print?";
$out=version();
print $out;
Output :
Linux
print $var; //prints nothing, Can pass variable in both ways
I thought $var will be global and can be seen there also.
If i consider the package it is still not available as
$main::var in package test
Can you please tell why?
Usually you would pass data as parameter to the function of the module.
in test.pm:
sub show {
my $var = shift;
print $var;
}
in test.pl:
use test;
show('test123');
this would print test123.