Why doesn't Perl's $OSNAME work on Solaris? - perl

I remember having used the variable $OSNAME in Linux.
Currently I'm working on a project on Solaris where I need to get the OS name and that variable is not working on Solaris.
Even a simple one line program does not work:
print "OS is $OSNAME\n";
it prints
OS is
Please help.

You need to use the English module.
$OSNAME is actually an alias for $^O, you can use $^O without using English module but to use $OSNAME you need to use the English module.
Also since use strict is missing you did not get any errors.
Always use use strict; in your program, it will help you catch these kinds of errors.
So try:
use English;
use strict;
print "Operating system is $OSNAME\n";

You can use print $^Oinstead.

Testing stuff from the command line, I get:
$ perl -E 'say $OSNAME'
$ perl -Mstrict -E 'say $OSNAME'
Global symbol "$OSNAME" requires explicit package name at -e line 1.
Execution of -e aborted due to compilation errors.
$ perl -Mstrict -MEnglish -E 'say $OSNAME'
linux

If $OSNAME ($^O) doesn't contain precisely the information you need, take a look at the values available to you from the Config module.

Related

A perl command line that prints the perl version it is using to run your script

I'd like to know if someone knows a function or command that I can put at the beginning of my Perl script that tells the user for example "this script is being run by perl v 5.XXX".
Specially when we have many versions installed.
$^V shows the "...revision, version, and subversion of the Perl interpreter." From perlvar.
You can use a special variable $]:
$ perl -e 'print $];'
5.014002

Is there a way to enable/disable Smart::Comments via a command line switch in my Perl program?

I'd like to enable/disable the comments within my Perl program that make use of the module Smart::Comments. I've toyed with the idea of doing this by providing a --verbose switch as part of my list of command line options. When this switch is set, I was thinking of enabling the Smart::Comment module like so:
#!/usr/bin/perl
use Getopt::Long;
use Smart::Comments;
my $verbose = 0;
GetOptions ('verbose' => \$verbose);
if (! $verbose) {
eval "no Smart::Comments";
}
### verbose state: $verbose
However this doesn't work for me. It seems to be something with the way Smart::Comments itself works, so I'm suspicious of the way in which I'm trying to disable the module with the eval "no ..." bit. Can anyone offer me some guidance on this?
Take out the use Smart::Comments line out of the script, and run you script with or without the -MSmart::Comments option. Using the -M<module> option is like putting a use <module> statement at the beginning of your script.
# Smart comments off
$ perl my_script.pl
# Smart comments on
$ perl -MSmart::Comments my_script.pl ...
Also see the $ENV{Smart_Comments} variable in the Smart::Comments docs.
Here, you would use Smart::Comments in your script like
use Smart::Comments -ENV;
and then run
$ perl my_script.pl
$ Smart_Comments=0 perl my_script.pl
to run without smart comments, and
$ Smart_Comments=1 perl my_script.pl
to run with smart comments.
Update The Smart::Comments module is a source filter. Trying to turn it on and off at runtime (e.g., eval "no Smart::Comments") won't work. At best, you can do some configuration at compile time (say, in a BEGIN{} block, before loading Smart::Comments):
use strict;
use warnings;
BEGIN { $ENV{Smart_Comments} = " #ARGV " =~ / --verbose / }
use Smart::Comments -ENV;
...
Use "if" pragma:
use if !$ENV{MY_APP_NDEBUG}, 'Smart::Comments';
# or
use if $ENV{MY_APP_DEBUG}, 'Smart::Comments';
This doesn't load Smart::Comments if not required.

How do I get the Perl's DateTime::Format::DateManip version number from the command line?

I'm using this from the command line:
perl -MDateTime::Format::DateManip -le 'print $Some::Module::VERSION'
but only return a blank line, any thoughts?
It is pseudo-code, Some isn't set so it is just printing out undef with the -l flag, like perl -le'print undef;
For evidence turn on warnings with -w
$ perl -MDateTime::Format::DateManip -wle 'print $Some::Module::VERSION'
Use of uninitialized value $Some::Module::VERSION in print at -e line 1.
Substitute Some::Module with the module you want the version of.
Also, just for fun ;)
Perl Shorthands for testing version numbers
These are quick ways to get version numbers by utilizing the use <module> <version> syntax and perl's vocal rejection of versions that aren't new enough.
These are all equivalent of creating a perl script with use DateTime 9999;
$ perl -MDateTime\ 9999
DateTime version 9999 required--this is only version 0.51.
BEGIN failed--compilation aborted.
However, this fashion isn't cross-platform, because you're simply telling bash to escape a space. This doesn't work in windows cmd, for that you'll have to
$ perl -M"DateTime 9999"
DateTime version 9999 required--this is only version 0.51.
BEGIN failed--compilation aborted.
Here, you just put it in quotes - that tells cmd to send it all as an argument to perl and it gets the same job done.
If you find yourself doing this frequently, you can download and install pmvers from CPAN. The script will save you from typing a potentially lengthy module name twice:
pmvers DateTime::Format::DateManip

Can I use perl's switches with /bin/env in the shebang line?

I want to run perl -w using env. That works fine on the command line:
$ /bin/env perl -we 'print "Hello, world!\n"'
Hello, world!
But it doesn't work on the shebang line in a script:
#!/bin/env perl -w
print "Hello, world!\n";
Here is the error:
/bin/env: perl -w: No such file or directory
Apparently env doesn't understand the -w flag that I'm passing to perl. What's wrong?
The hash-bang isn't a normal shell command-line, the parsing and white-space handling is different - that's what you've hit. See:
http://www.in-ulm.de/~mascheck/various/shebang/
http://homepages.cwi.nl/~aeb/std/hashexclam-1.html#ss1.3
http://en.wikipedia.org/wiki/Shebang_(Unix)
Basically many/most unixes put all of the remaining text after the first space into a single argument.
So:
#!/bin/env perl -w
is the equivalent of:
/bin/env "perl -w"
so you need to handle any options to the perl interpreter in some other fashion. i.e.
use warnings;
(as #Telemachus)
Instead of -w use the warnings pragma (for modern versions of Perl):
#!/bin/env perl
use warnings;
use strict;
I thought it might be useful to bring up that "-w" is not the same as "use warnings". -w will apply to all packages that you use, "use warnings" will only apply lexically. You typically do not want to use or rely upon "-w"
It's worth noting that Mac OS X interprets characters after the shebang as arguments, so on OS X, the following will work:
#!/usr/bin/env perl -wT
enter code here
However, since one of the points of using #!/usr/bin/env is to foster cross-platform compatibility, it's probably best not to use that syntax even if you're on a Mac mostly.

How can I find the version of an installed Perl module?

How do you find the version of an installed Perl module?
This is in an answer down at the bottom, but I figure it important enough to live up here. With these suggestions, I create a function in my .bashrc
function perlmodver {
perl -M$1 -e 'print "Version " . $ARGV[0]->VERSION . " of " . $ARGV[0] . \
" is installed.\n"' $1
}
Most modules (especially ones from The CPAN) have a $VERSION variable:
perl -MSome::Module -le 'print $Some::Module::VERSION'
Why are you trying to get the version of the module? Do you need this from within a program, do you just need the number to pass to another operation, or are you just trying to find out what you have?
I have this built into the cpan (which comes with perl) with the -D switch so you can see the version that you have installed and the current version on CPAN:
$ cpan -D Text::CSV_XS
Text::CSV_XS
-------------------------------------------------------------------------
Fast 8bit clean version of Text::CSV
H/HM/HMBRAND/Text-CSV_XS-0.54.tgz
/usr/local/lib/perl5/site_perl/5.8.8/darwin-2level/Text/CSV_XS.pm
Installed: 0.32
CPAN: 0.54 Not up to date
H.Merijn Brand (HMBRAND)
h.m.brand#xs4all.nl
If you want to see all of the out-of-date modules, use the -O (capital O) switch:
$ cpan -O
Module Name Local CPAN
-------------------------------------------------------------------------
Apache::DB 0.1300 0.1400
Apache::SOAP 0.0000 0.7100
Apache::Session 1.8300 1.8700
Apache::SizeLimit 0.0300 0.9100
Apache::XMLRPC::Lite 0.0000 0.7100
... and so on
If you want to see this for all modules you have installed, try the -a switch to create an autobundle.
VERSION is a UNIVERSAL method of all Perl classes. You can use it to get the module version (if it has been set which it usually has).
Here is a one liner where you only have to add the module name once:
perl -le 'eval "require $ARGV[0]" and print $ARGV[0]->VERSION' Some::Module
There is a less-typing trick, that works provided your module doesn't have something insane like a Unix timestamp as a version number.
perl -MFoo::Bar\ 9999
This works because what it translates to is
use Foo::Bar 9999;
i.e. a version of Foo::Bar that's at least version 9999 or newer.
And what you get is
Foo::Bar version 9999 required--this is only version 1.1.
BEGIN failed--compilation aborted.
(Neat trick I learned from Matt Trout.)
If you are lucky, the module will have a package variable named $VERSION:
$ perl -MCPAN -e 'print "$CPAN::VERSION\n"'
1.9205
This is needed for modules to be distributed on CPAN, but internally developed modules might follow a different convention or none at all.
Thanks for the answers! I've created a function in my .bashrc to easily find the version of a Perl module:
function perlmodver {
perl -M$1 -e 'print $ARGV[0]->VERSION . "\n"' $1
}
Easiest to remember and most robust version for me:
perl -e 'use Search::Elasticsearch; print $Search::Elasticsearch::VERSION;'
Check out the pmtools scripts on CPAN. If you're using a Debian(-based) distro, there's also a handy pmtools package. This includes a script "pmvers" that tells you a module's version. It's quite handy.
It does something similar to the various one-liners folks posted, but it's a bit smarter about error handling, and can give you the version of more than one module at once.
I wrote a small script to report that: perlver.
This is a simple little tool that
tells you what version of a module you
have installed, and where the .pm file
is located. It also ensures the module
can be loaded successfully. It
automatically converts ‘-’, ‘/’, or
‘\’ to ‘::’, so you can use a pathname
or distribution name instead of the
canonical module name.
It assumes that the module defines a $VERSION. If the module doesn't define a $VERSION, it will still tell you where the .pm file is, so you can examine it manually. You can also check several modules at once:
$ perlver CPAN DBD-Pg Getopt::Long
CPAN 1.7602 is
/usr/lib/perl5/5.8.8/CPAN.pm
DBD::Pg 1.49 is
/usr/lib/perl5/vendor_perl/5.8.8/i686-linux/DBD/Pg.pm
Getopt::Long 2.36 is
/usr/lib/perl5/vendor_perl/5.8.8/Getopt/Long.pm
In addition, for modules that use Exporter.pm, you can get this information with this trick:
perl -MSome::Module=99999 -ex
Some::Module version 99999 required--this is only version 1.9205 at ...
For modules that don't use Exporter.pm, a slightly longer trick reports the same information:
perl -e'use Some::Module 99999'
Some::Module version 99999 required--this is only version 1.9205 at ...
We have the system perl (/usr/bin/perl) in Solaris 10, and above solutions are useless. Some of them report "module.pm is not installed", some of them have no output.
Here is the code which is helpful, which can list all modules and their version.
#!/usr/bin/perl
use strict;
use ExtUtils::Installed;
my #modules;
my $installed = ExtUtils::Installed->new();
if (scalar(#ARGV) > 0) {
#modules = #ARGV;
} else {
#modules = $installed->modules();
}
print "Module\tVersion\n";
foreach (#modules) {
print $_ . "\t" . $installed->version($_) . "\n";
}
You can also take a look at App::module::version
$ module-version
The version of App::module::version in /home/yourself/perl5/lib/perl5 is 1.004