I would like to use the $var variable in lib path.
my $var = "/home/usr/bibfile;"
use lib "$var/lib/";
However when I do this it throws an error.
I'd like to use use lib "$var/lib/";instead of use lib "/home/usr/bibfile/lib/";.
How can I assign a variable, so that it can be used in the setting of lib modules?
Variables work fine in use lib, well, just like they do in any string. However, since all use directives are executed in BEGIN block, your variable will be not yet initialized at the moment you run use, so you need to put initialization in BEGIN block too.
my $var;
BEGIN { $var = "/home/usr/bibfile"; }
use lib "$var/lib/";
use Data::Dumper;
print Dumper \#INC;
Gives:
$VAR1 = [
'/home/usr/bibfile/lib/',
# ... more ...
];
Not sure about what you're trying to accomplish, but seems like a task for FindBin::libs:
my $var;
BEGIN { $var = "/home/usr/bibfile" };
use FindBin::libs "Bin=$var", "base=lib";
You can't, because the use directive is evaluated at compile time, while other variables are evaluated at runtime.
If your lib is located somewhere relative to your original script, you can use the standard module FindBin:
# $Bin from FindBin is the directory of the original script
use FindBin;
use lib "$FindBin::Bin/path/to/bib";
use MyModule;
Related
This has probably been asked before, but I'm not sure what to search for. The problem is that I'm dealing with a package that is 4 directories deep and has a rather long name. Within the package are some exported constants that I want to use in main, but I don't want to use their fully qualified names, nor do I want to use their local name (the part after the last ::). For example.
use strict;
use warnings;
use Vendor::FirstPackage::SecondPackage::ThirdPackage qw(const_a);
# this is works, but I want to include the last package
my $x = const_a;
# this throws bareword error
my $y = ThirdPackage::const_a;
# this throws undefined subroutine
my $z = ThirdPackage::const_a();
Is there a way to access the constant via it's last package name?
use Package::Alias 'ThirdPackage' => 'Vendor::FirstPackage::SecondPackage::ThirdPackage';
But I'd recommend just using the fully qualified name.
You can create a package like this in your main script:
package ThirdPackage;
use strict;
use Vendor::FirstPackage::SecondPackage::ThirdPackage qw(const_a);
Then you should be able to access const_a as ThirdPackage::const_a. If you will put that package at the beginning of your main script, then main code should be separated with package main;
You could use Module::Load like this:
use strict;
use warnings;
use Module::Load qw(load_remote);
BEGIN {
load_remote 'ThirdPackage', 'Vendor::FirstPackage::SecondPackage::ThirdPackage', qw(const_a);
}
my $x = ThirdPackage::const_a;
I am able to use the variables from imported .pm file. I can use the variables from .pl file. But when I add 'use strict' to the code it didnt work.
I tried the following
source.pl
{
var = 22;
}
1;
main.pl
use strict;
my $ref = do "source.pl";
my ($mainvar) = #$ref{ qw(var) };
print "$mainvar\n";
here its printing the $mainvar as empty string. Please help
There are two basic Perl variable types:
my - These are lexically scoped. This means that they fall in and out of existence depending upon where they're defined. Lexically scoped variables are only defined in the block they're in. If they're defined in a file, they're only accessible to that file.
our - These are package variables. A package is just Perl creating a namespace that's specific to that area of the code (usually an entire file).
In Perl, when you're in a package, you can use the variables without any prefix. Otherwise, you need to prefix variable (and subroutine names) with their package name. Think of File::Find's$File::Find::dir. That's the$dirvariable in theFile::Find` package.
When you use strict;, you must either declare your variable with either our (for package variables or my (for lexically scoped variables, or use the full package name of that variable:
source.pl
use strict;
use warnings;
our $var = 22;
test.pl
use strict;
use warnings;
do "source.pl";
our $var; #Merely a declaration -- Doesn't change the value
my $local_var = $var;
print "$local_var\n";
You could have done this too:
use strict;
use warnings;
no warnings qw(once);
do "source.pl";
my $local_var = $main::var; #Specified full package name of variable
print "$local_var\n";
I had to use no warnings qw(once); to remove the warning that $main::var is only used once.
I have a question relating to Perl and scoping. I have a common file with lots of various variables. I require the common file in my main script, but I cannot access the variables; they seem to be outside of its scope. I assumed that an our declaration would overcome that problem, but it doesn't seem to work.
Script 1: common.pl
#!/usr/bin/perl
our $var1 = "something";
our $var2 = "somethingelse";
Script 2: ftp.pl
#!/usr/bin/perl
use strict;
use warnings;
require('common.pl');
print $var1;
I get the error: Global symbol "$var1" requires explicit package name
There's no require statement in your second example, but it wouldn't work anyway. What our does is declare a lexically-scoped package variable. Since you have no package statement, it uses the default package main. So your first script sets up the variable $main::var1, but this will only be available within that file's scope.
A better way to provide common variables for other scripts is to use Exporter. You can define package symbols in one place and Exporter will take care of copying them to the requesting script or class's namespace when needed.
I would put the config in a module instead.
File: MyConfig.pm
package MyConfig;
require Exporter;
use strict;
our #ISA = qw(Exporter);
our #EXPORT = qw( getconfig );
my %confighash = (
thisone => 'one',
thatone => 2,
somthingelse => 'froboz',
);
sub getconfig {
return %confighash;
}
1;
Example usage:
#!/usr/bin/perl
use strict;
use warnings;
use MyConfig;
my %config = getconfig();
print $config{ somthingelse };
This should print froboz
It looks like you need a proper configuration file there. I'd go for a non-code configuration file that you can read when you need to setup things. There are modules on CPAN to handle just about any configuration format you can imagine.
If you want to do it the way you have it, get rid of our and declare them with use vars. Don't let the PBP police scare you off that. :) You only really need our to limit a scope of a package variable, and that's exactly the opposite of what you are trying to do.
our() does something a little different than you think. Its sole purpose is to work with strict in requiring you to declare package variables that you are going to use (unless they are fully-qualified or imported). Like strict, its effect is lexically-scoped. To use it to allow accessing a global $main:var1 from multiple files (which are separate scopes) as just $var1, you need to say our $var1 in each file.
Alternatively, you would change your required file to be a module with its own package that exports the variables to any package that uses it.
Try this. I am new at Perl but this is how I got it to work on a script I made
#!/usr/bin/perl
$var1 = "something";
$var2 = "somethingelse";
Script 2: ftp.pl
#!/usr/bin/perl
use strict;
use warnings;
our $var1;
our $var2;
require('common.pl');
print $var1;
This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
How do I include functions from another file in my Perl script?
I have a perl file suppose a.pl and I want to use a function from perl file b.pl. How do i do it
Turn b.pl into a module
Call it something descriptive like MyBModule (B is reserved by core).
rename the file to the something .pm like MyBModule.pm.
Add a package at the top, like package MyBModule;
Set a true return code on the package by making the last line 1;
You don't have to do anything else if you want to use your package name when calling the sub.
use MyBModule;
use strict;
use warnings;
MyBModule::sub1();
If you don't want to qualify it with the package name, read on...
Use Exporter.pm
Now configure Exporter.
Add the use Exporter; statement at the top of your module.
add a line our #EXPORT_OK = qw(sub1 sub2);
After you're done your module should look something like this
package MyBModule;
use strict;
use warnings;
use Exporter;
our #EXPORT_OK = qw(sub1 sub2);
sub sub1 { ... }
sub sub2 { ... }
Edit the caller
Make sure the library is in #INC, or the module in the current directory. If not append the directory to PERL5LIB.
Add a line like use MyBModule qw(sub1 sub2);
Read perldoc Exporter for more information
Your script should look like this afterward:
use strict;
use warnings;
use MyModuleB qw( sub1 sub2 );
It really isn't that hard, it takes about 15 seconds after you get used to doing it.
The best/conventional way is to keep all your functions in a Perl module file (.pm): See perlmod. This would require you to convert b.pl to a package. You would then access your module file (MyFuncs.pm) from a.pl with:
use MyFuncs;
Use the require and/or use functions.
Use the 'use' keyword to use functions from another module.
Example:
File a.pl:
use b;
f_in_b();
File b.pm:
sub f_in_b()
{
print "f_in_b\n";
}
1;
Important:
File b.pm must have the final 1;
I have a dir called foo, and in that I have lib and bin. The scripts in bin need stuff in lib. I do something like this:
#!perl
use strict;
use warnings;
use lib '../lib';
use Foo; # <-- comes from lib
But that means I have to be in the bin dir to run the script. Surely there is a better way. What's the Right Way to do this?
The standard FindBin module does what you want.
use FindBin;
use lib "$FindBin::Bin/../lib";
perldoc FindBin for more.
Parse out the complete path to your .pl via __FILE__ and and tack the ../lib on the end or pop off the last element of split(/\//,__FILE__) and add /lib to that.
I generally use this technique. Its sadly inspired from my PHP days:
Its handy in situations where you know where a given file will be relative to the current one, and aren't sure of the entry points it may be called in or the surrounding environment at calltime.
However, I would generally use this technique only for test scripts which need dummy libraries for emulating things.
use File::Basename ();
use Cwd ();
my $base_dir;
my $relative_path;
BEGIN {
$relative_path = '../../' # Path to base of project relative to the current file
$base_dir = Cwd::realpath( File::Basename::dirname(__FILE__) .'/' . $relative_path );
}
use lib "${base_dir}/lib";
use Foo;
Ideally there should be some module somewhere that does this, if not, I'm half tempted to write one:
use Some::Module ();
use lib Some::Module::relative_self('../../lib', __FILE__ );
The "FindBin" module will only work if the directory that the perl script resides in is in your system PATH, else it will fail. To overcome that you can manipulate the $0 value to get your path-to-perl-module information and pass the value to use lib.
Something like this -
BEGIN {
use File::Spec::Functions qw(rel2abs);
use File::Basename qw(dirname);
#Covert the script path to absolute and get its directory name
our $path = dirname( rel2abs($0) );
#Replace the bin tag with lib to get module directory
$path =~ s{bin/?$}{lib};
}
use lib $path;
EDIT:
The FindBin module works just perfectly and can be used as described in Michael's answer. My understanding of its workings was incomplete and so led me to making the first comment which I now retract. Anyway, I don't see any reason why this method shouldn't work albeit with a few more lines than could be achieved using FindBin (TMTOWTDI).
use lib './';
has been working for me with Perl v5.14.2 on a linux box to include files in the same directory as my script.
Perhaps it would work for you to move your lib and bin directories under your script's working directory and try to reference them using
use lib './bin/';
My solution:
use lib substr(__FILE__, 0, rindex (__FILE__, "/"));
Just to add my own two cents to this collection of answers, I usually solve this problem using something along these lines:
use lib do {
use Cwd 'realpath';
my ($dir) = __FILE__ =~ m{^(.*)/}; # $dir = path of current file
realpath("$dir/../lib"); # path of '../lib' relative to $dir
};
I like using a do block because everything needed is so neatly contained therein. If you ever need to copy/paste, or try to understand your code at a later time you don't have to look for a separate BEGIN block or anything like that.
The above code naïvely assumes that / is used as a dir/filename separator.
How about:
BEGIN: {
push #INC, '/full/path/to/lib';
}
To do a relative reference would assume that you're going to keep it in the bin dir, so insert the relative reference there instead.