Perl Examples

Published on Author gryzli

The main idea of posting this post is for my own comfort (so I can find these things when I need them).

The code examples may not be suitable for direct insertion inside your script. 

 

Find the files location of a perl module

perldoc -l Some::Module

 

Check if perl module is part of the core modules with Module::CoreList 

There is a very handy module called “Module::CoreList” which resides inside perl core from version v5.8.9. 

The module comes with pre-installed binary as well called “corelist”, which is handy for use: 

# Search for a given module 
gryzli@localhost ]$ corelist List::Util 

Data for 2018-11-29
List::Util was first released with perl v5.7.3


# Search for all modules matching a regex 
gryzli@localhost [~/temp/perl_book]$ corelist /List/ 

Data for 2018-11-29
I18N::LangTags::List was first released with perl v5.7.3

Data for 2018-11-29
List::Util was first released with perl v5.7.3

Data for 2018-11-29
List::Util::PP was first released with perl v5.10.1 and removed from v5.17.1
........
.......
.....

You could also use it inside perl script. 

The following example will list you all core modules for a given perl version (ex: 5.10.0) . 

#!/usr/bin/perl 

use strict;
use warnings;
use Module::CoreList; 

my $max_size = max map { length } keys %{$Module::CoreList::version{5.010000}}; 
foreach ( sort keys %{$Module::CoreList::version{5.010000}} ) {
	printf "Module: [%*s], First release:%s \n",- $max_size, $_,Module::CoreList->first_release($_); 
}

 

Working with perl lib directories and modules 

 

Loading modules during runtime (not compile time)

If you are using “use XXX;” this loads the module during script compile time. 

You are also able to load a module during the run time, by using “require“.

 

Manually installing module from CPAN

If you can’t install a package from CPAN with cpan or cpnam for some reason, you can compile it manually. The process is simple: 

# Download the module, ex: Perl::Critic
wget https://cpan.metacpan.org/authors/id/P/PE/PETDANCE/Perl-Critic-1.132.tar.gz

# Untar the module 


# Compile it 


# IF MAKEFILE.PL %

perl Makefile.PL INSTALL_BASE=/home/gryzli/perl5
make 	
make test 
make install 

# IF Build.PL % 

perl Build.PL --install_base /home/gryzli/perl5
perl Build 
perl Build test 
perl Build install 

The example above shows 2 different ways of compiling a module, depending on whether it has Makefile.PL or Build.PL. 

Also there is additional argument “–install_base and INSTALL_BASE env” , which are telling make to install the module locally in my /home/gryzli/perl5 directory.

 

Adding additional lib directories to perl

Sometimes you may need to load perl module from a custom directory, not mentioned in your default perl @INC. 

There are several ways to accomplish this, here are some examples: 

Inside your perl script

# Modifications of @INC should be made inside BEGIN {}, because USE are run during compilation time 
BEGIN { unshift @INC, '/path/to/MyModule/some'}; 
use MyModule::Some; 

# Better is to use the 'use lib' pragma 
use lib  '/path/to/MyModule/some'; 
use MyModule::Some; 

 

Outside your perl script

# Modify the PERL5LIB environment variable, prior script execution 
# this could be made persistent in .bashrc/.bash_profile
export PERL5LIB="$PERL5LIB:/path/to/my/module" 
perl some_script.pl 


# Adding custom libdir with -I during the script invocation
perl -I /path/to/my/module  some_script.pl 

 

Reading file content

Some interesting method with do {} 

my $file_contents = do {
  local $/;
  local @ARGV = ( $filename );
  <>
};

 

 

 

Dynamic Function List Execution With GetOpts And Dispatcher

Sometime you want to associate each new argument to your perl script, with separate function. If you write a lot of functions during the development, adding each function as an argument option (inside GetOptions) and also defining separate If() statement for checking it, could be boring. 

In this case you can try executing the function dynamically, by using something like this: 

#!/usr/bin/perl 
use strict;
use warnings;

my %opt;
my %dispatch =  (
        your_new_argument => \&your_new_function,
);

GetOptions (\%opt,
        keys %dispatch,
) ;

# Check what has been supplied as argument and execute it 
foreach my $action (keys %dispatch){
        $dispatch{$action}->()  if defined ($opt{$action});
}


sub your_new_function { 
    print "Hello from your_new_function() \n"; 
} 

 

 

 

Generating Usage/Man like help with Pod::Usage

If you are tired of writing usage() or help() functions for showing usage notes about your program, you may wish to consider Pod::Usage. 

By using it, you will have consistent formatting through your help messages, and also will save some code. 

 

Here it is a simple example: 

use Pod::Usage qw(pod2usage);
use Getopt::Long qw (GetOptions);

# Parse the options
my %opt; 
GetOptions (\%opt, 
        "h|help",
        "man"
); 



# Print Usage 
if (defined $opt{h} or defined $opt{help}){
        pod2usage(0);
}
if (defined $opt{man} ){
        pod2usage(-verbose => 2);
}

# .....
# .....
# some code 
# ....


__END__

=head1 NAME

sample_script.pl

=head1 SYNOPSIS

sample_script.pl [options] 

=head1 OPTIONS

=over 4

=item B<--help>

Print a brief help message and exits.

=item B<--man>

Print extensive help page in Man Style 

=back

=head1 DESCRIPTION

Example script 

=head1 AUTHOR

Written by Gryzli The Bugbear

=head1 COPYRIGHT

Copyright  2019,  Gryzli.Info, all rights reserved.

=cut

 

Showing the short version of the help 

gryzli@localhost [~/temp]$ perl sample_script.pl  --help 
Usage:
    sample_script.pl [options]

Options:
    --help
        Print a brief help message and exits.

    --man
        Print extensive help page in Man Style

By running it with “–man” you could go to a man-like page , which will visualize all of the information in your POD. 

 

 

 

Using DateTime To Work With Dates

use DateTime;

# Print hh:mm:ss time 
print DateTime->now->hms 

# Print YY-MM-DD 
print DateTime->now->ymd


## OO Notation 
# Get current date 
my $date = DateTime->now()

# Print current time in EPOCH (unix timestam)
say $date->epoch(); 

 

 

Changine the umask of your script

Some time you may need to change the default umask in order to affect newly created files by your perl script. This could be easily done by adding the following to your script:

# Changing umask to 077 
umask 077;

More about how umask works under Linux, could be read here:

https://wiki.archlinux.org/index.php/umask

 

Changing PATH environment variable

Sometimes you may need to execute binaries from path which is not currently inside your environment variable.

Also if your script is running as a CRON job, most probably your PATH would be much limited.

Adding new directories to PATH inside perl script is as easy as:

$ENV{PATH}="/usr/bin:/bin:/usr/local/bin:/usr/sbin:/sbin:/usr/local/sbin:$ENV{PATH}";

It is good to append your current PATH to the end of the newly modified PATH string.

 

Adding random sleep / wait

# This will choose random number between 0 - 100 and wait these seconds
sleep(int(rand(100)));

If you need to add sleep for a period less than a second , it would be good idea to use Time::HiRes perl module.

use Time::HiRes; 

# Sleep for microseconds 
usleep ($microseconds);

# Sleep for nanoseconds
nanosleep ($nanoseconds);

 

 

Check if script is running under screen session

Sometimes we write scripts that are intended to be run inside screen sessions for the sake of safety.

You could add check inside your script to make sure it is run inside screen session:

# Exit if we are not running inside screen session 
if (not defined $ENV{STY}){
    print "ERROR: You are NOT in SCREEN session, please make sure you execute the script inside screen\n";
    exit 1;
}

 

Escaping shell commands

If you need to escape certain shell commands, you could use String::ShellQuote  .

use String::ShellQuote ; 
my $quoted_command = shell_quote "some shell command" ;

 

Storing and Loading object with Storable

If you need to store your object and later re-load it with all of it’s data , you could use “Storable” module.

You could actually store your object and reload it in another script run and you will be able to access it’s functions and variables.

use Storable; 

# Storing the object
store $my_object_reference , "file_to_store"; 

# Loading back the object 
my $object_ref = retrieve("file_to_store");

 

Simple and safe logging to a file for multiple concurrent processes using a lock

Let say you want to log events to a log and you have multiple scripts running in the same time and trying to save events to the same log file.

There is a pretty big chance the different processes to overlap lines in the log.

One of the ways you can achieve this is by  Log::Log4perl::Appender::Synchronized .

If you want to make it less complicated, you could use function like this:

sub logger {
        my ($msg) = @_; 
        my $logfile="/path/to/some/log.log"
        open my $fh, ">>", $logfile;
        flock $fh, LOCK_EX;
        print {$fh} $msg."\n";
        close $fh;
} 

# Log something

&logger ("Some message here");

 

Resources

Perl Simple Web Hit Function Using LWP 

https://xdg.me/blog/