local perl setup

install perlbrew

\curl -L http://install.perlbrew.pl | bash

install local perl and cpanm

After restarting your shell or sourcing the files installed by perlbrew you can build a new perl version that can be installed locally. Afterward, you can install cpanm to install perl packages using the local perl you just built.

PERL_VERSION="perl-5.35.10"
perlbrew install ${PERL_VERSION}
perlbrew switch ${PERL_VERSION}
perlbrew install-cpanm

find files with perl

Try the handy find2perl utility that comes with perl and uses the File::Find package. It writes a little script for you that you can adapt. See the perldoc site for further details.

An example from the documentation

find2perl / -name .nfs\* -mtime +7 \
-exec rm -f {} \; -o -fstype nfs -prune
``

Gives you a `wanted` subroutine like so:

```perl
sub wanted {
    /^\.nfs.*\z/s &&
    (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_)) &&
    int(-M _) > 7 &&
    unlink($_)
    ||
    ($nlink || (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_))) &&
    $dev < 0 &&
    ($File::Find::prune = 1);
}

Here’s a modification that gives you files ending in txt modified between 50 and 20 days ago.

sub wanted {
    my ($dev,$ino,$mode,$nlink,$uid,$gid);

    /\.txt\z/s &&
    (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
    (int(-M _) < 50) && (int(-M _) > 20)
    && print("$name\n");
}

find perl module location

Basically, @INC gives you the locations of modules; %INC is a hash with the keys as modules and values as locations of the module.

perl -MXSLoader -lE 'map { print join(" ", $_, "=>", $INC{$_}); } keys %INC'

You can also achieve the same effect of figuring out where the module is located using perldoc.

perldoc -lm XSLoader

perl DBD::mysql

By default DBD::mysql does not compile in ssl. The simplest way to have it compile with ssl is to set the environmental variable, export DBD_MYSQL_SSL=1. If you install it with cpanm, for instance, it will install correctly if you set the environmental variable.

There are other environmental variables, too, that can be set, mostly to assist with testing. See perldoc DBD::mysql.

perl text manipulation

command line

split lines automatically on white-space

Splitting text on the command line with -a creates @F automatically, which has all of the processed text. It must be used with either the -n or -p options, which both place a loop around your script. The difference being that -p executes your commands and prints the value of $_ afterward.

perl -nalE '{ print $F[3]; }' some_file

specify how to split each line with -F

Specifying -F implicitly sets -a and -n. To split using the semicolon try:

perl -F';' -lE '{ print $F[2]; }' some_file

read csv

use Text::CSV_XS;
use Text::Iconv;
my $csv_reader = Text::CSV_XS->new({auto_diag => 1, binary => 1});

write csv

use Text::CSV_XS;
my $csv_writer = Text::CSV_XS->new({
    binary => 1, auto_diag => 1, always_quote => 1, eol => "\n"
});

read xls

use Spreadsheet::ParseExcel;
my $parser   = Spreadsheet::ParseExcel->new();
my $workbook = $parser->parse($file);

read xlsx

Note, that you do not necessarily need to use the converter.

use Spreadsheet::XLSX;
use Text::Iconv;
my $converter = Text::Iconv->new("utf-8", "windows-1251");
my $in_excel = Spreadsheet::XLSX->new($file, $converter);

write xlsx

use Excel::Writer::XLSX;
my $workbook = Excel::Writer::XLSX->new("$out_ext.xlsx");
$workbook->set_properties(
    title    => "data created by $prog_name on $now_time",
    author   => 'TS Wingo',
    comments => 'created with perl and Excel::Writer::XLSX'
);

perl serializing data

JSON - for machines

use JSON
my $json = new JSON;
print $json->pretty(1)->encode(\%data);

YAML - for humans

use YAML qw(Dump Bless);
print Dump(\%data);

perl dates/times

read dates and make a DateTime object

use DateTime;
use DateTime::Format::Strptime;

# some common ones I've (unfortuneately) encountered

# YYYY-MM-DD
my $strp_dt_iso    = DateTime::Format::Strptime->new(
    pattern => '%F', on_error => 'croak'
);

# MM/DD/YYYY HH:MM:SS AM/PM (12h time)
my $strp_dt_us_12h = DateTime::Format::Strptime->new(
    pattern => '%m/%d/%Y %I:%M:%S %p', on_error => 'croak'
);

# MM/DD/YYYY
my $strp_dt_us     = DateTime::Format::Strptime->new(
    pattern => '%m/%d/%Y', on_error => 'croak'
);

# DD-Mos-YY (month = 3 letter abbreviation)
my $strp_dt_crazy  = DateTime::Format::Strptime->new(
    pattern => '%d-%B-%y', on_error => 'croak'
);

# parse
$dt = $strp_dt_us->parse_datetime($this_data{date});

## get current time?

use Time::localtime;
# time
my $now_time       = ctime();
# date
my $now_timestamp  = sprintf("%d-%d-%d", eval(localtime->year() + 1900),
    eval(localtime->mon() + 1), localtime->mday());

## file modified time

use Time::localtime;
use File::stat;
$date_string = ctime(stat($file)->mtime);

perl HERE documents

Here’s an overview how to use them.

non-interpreted

my $cmd = <<'EOF';
#!/bin/sh
touch file.tmp
EOF

print $cmd;

interpreted

my $cmd = <<"EOF";
#!/bin/sh
touch $this_file
EOF

print $cmd;

white space

If you have indented things and you want the here document to be alignged just tell perl to get rid of the leading whitespace like so.

(my $cmd = <<"EOF") =~ s/\A\s+//gm;
...
EOF

perl’s q{} or qq{} commands

Another option is just to use qq or q (depending on whether you want to interpolate things).

(my $cmd = qq{
#!/bin/sh
touch $this_file
}) =~ s/\A\s+//mg;

perl error handling

Lots of people like Try::Tiny, which is fine. I have used the following approach. Basically, you just put the thing that might fail in an eval block, as per usual, and inspect the return value (without necessarily depend on $@ to have the right error since it can be clobbered sometimes).

eval {

    # do something that fails
    1 / 0;

    # return true to indicate success
    1;
}
or do {

    # say something about it and have a default statement
    my $error = $@ || 'unknown failure';

    # notice you'll need the semi-colon unless you're at the end of a block
};

See this stackoverflow and perltv.org for more details.

perl cheat sheet

Originally found here.

CONTEXTS  SIGILS             ARRAYS        HASHES
void      $scalar   whole:   @array        %hash
scalar    @array    slice:   @array[0, 2]  @hash{'a', 'b'}
list      %hash     element: $array[0]     $hash{'a'}
&sub
*glob    SCALAR VALUES
number, string, reference, glob, undef
REFERENCES
\     references      $$foo[1]       aka $foo->[1]
$@%&* dereference     $$foo{bar}     aka $foo->{bar}
[]    anon. arrayref  ${$$foo[1]}[2] aka $foo->[1]->[2]
{}    anon. hashref   ${$$foo[1]}[2] aka $foo->[1][2]
\()   list of refs
                        NUMBERS vs STRINGS  LINKS
OPERATOR PRECEDENCE     =          =        perl.plover.com
->                      +          .        search.cpan.org
++ --                   == !=      eq ne         cpan.org
**                      < > <= >=  lt gt le ge   pm.org
! ~ \ u+ u-             <=>        cmp           tpj.com
=~ !~                                            perldoc.com
* / % x                 SYNTAX
+ - .                   for    (LIST) { }, for (a;b;c) { }
<< >>                   while  ( ) { }, until ( ) { }
named uops              if     ( ) { } elsif ( ) { } else { }
< > <= >= lt gt le ge   unless ( ) { } elsif ( ) { } else { }
== != <=> eq ne cmp     for equals foreach (ALWAYS)
&
| ^              REGEX METACHARS            REGEX MODIFIERS
&&               ^     string begin         /i case insens.
||               $     str. end (before \n) /m line based ^$
.. ...           +     one or more          /s . includes \n
?:               *     zero or more         /x ign. wh.space
= += -= *= etc.  ?     zero or one          /g global
, =>             {3,7} repeat in range
list ops         ()    capture          REGEX CHARCLASSES
not              (?:)  no capture       .  == [^\n]
and              []    character class  \s == [\x20\f\t\r\n]
or xor           |     alternation      \w == [A-Za-z0-9_]
                    \b    word boundary    \d == [0-9]
                    \z    string end       \S, \W and \D negate
DO
use strict;        DON'T            LINKS
use warnings;      "$foo"           perl.com
my $var;           $$variable_name  perlmonks.org
open() or die $!;  `$userinput`     use.perl.org
use Modules;       /$userinput/     perl.apache.org
                                    parrotcode.org

FUNCTION RETURN LISTS
stat      localtime    caller         SPECIAL VARIABLES
0 dev    0 second     0 package      $_    default variable
1 ino    1 minute     1 filename     $0    program name
2 mode   2 hour       2 line         $/    input separator
3 nlink  3 day        3 subroutine   $\    output separator
4 uid    4 month-1    4 hasargs      $|    autoflush
5 gid    5 year-1900  5 wantarray    $!    sys/libcall error
6 rdev   6 weekday    6 evaltext     $@    eval error
7 size   7 yearday    7 is_require   $$    process ID
8 atime  8 is_dst     8 hints        $.    line number
9 mtime               9 bitmask      @ARGV command line args
10 ctime  just use                    @INC  include paths
11 blksz  POSIX::      3..9 only      @_    subroutine args
12 blcks  strftime!    with EXPR      %ENV  environment

perl books

perl moose