Saturday, November 21, 2015

Quick Language Reference: Perl

for executable scripts

    path to perl, first line can have hashbang
    #!/usr/bin/perl

    for portability, first line can have hashbang
    #!/bin/env perl

    a space after ! is ok
    #! /usr/bin/perl


test for errors:

    cat filename | perl -cw

show all lib paths

    perl -e 'print join "\n", @INC;'

look for installed libs

    perl -e 'print join "\n", @INC;' | while read f; do find $f -follow; done \
      | grep XML | sort | uniq

look for which libs are used

    #(all the use statments)
    grep -R -e '^use' .  | sed -e 's/^[^:]*://' -e 's/\s*;.*$//' \
      | sort | uniq

    #(just the lib names)
    grep -R -e '^use' .  | sed -e 's/^[^:]*://' -e 's/\s*;.*$//' \
      |  awk '{print $2}' | sort | uniq

show installed/cpan versions

    #!/usr/bin/perl
    # pass perl module name/regex as arg
    # eg:
    #     DBI /DBD::/

    use CPAN;

    printf("%-20s %10s %10s\n", "Module", "Installed", "CPAN");

    foreach $a (@ARGV) {
      foreach $mod (CPAN::Shell->expand("Module", $a)){
        printf("%-20s %10s %10s %s\n",
          $mod->id,
          $mod->inst_version eq "undef" || !defined($mod->inst_version)
            ? "-" : $mod->inst_version,
          $mod->cpan_version eq "undef" || !defined($mod->cpan_version)
            ? "-" : $mod->cpan_version,
          $mod->uptodate ? "" : "*"
        );
      }
    }


print library paths

    perl -e 'printf "%d %s\n", ++$i, $_ for @INC'

    #1 /wcs/lib/perl5/5.6.1/i686-linux-perlio
    #2 /wcs/lib/perl5/5.6.1
    #3 /wcs/lib/perl5/wcs/5.6.1/i686-linux-perlio
    #4 /wcs/lib/perl5/wcs/5.6.1
    #5 /wcs/lib/perl5/wcs
    #6 .


installation preference:

    1. try yum, if that doesn't work
    2. install with CPAN.  if that doesn't work
    3. compile manually (avoid if possible)

install perl libs with yum

    yum install
    #for example:
    yum install perl-Apache*


install perl with cpan

    perl -MCPAN -e 'install CGI::Builder'


manual installation

    # general process to compile c programs
    ./configure
    make
    make test
    make install


command line args

    # first argument:
    $ARGV[0]

file perms

    must have execute perms on script files

hello world

    print "hello\n";

http header:

    print "content-type: text/html \n\n";    #HTTP HEADER


require strict variable defs

    #!/bin/perl
    use strict;


perl variable markers

    $ for strings, literals
    @ for arrays
    % for hash (associative array)


strings

    "interprets $var variables"
    'literal syntax no interpolation'

string concat

    .

string length

 
    length()

remove new line

    chomp()



# perl heredoc syntax
$heredoc = <
<END;
     Everything after the
     start of the
     here-doc is part of
     the string until we get
     to the
END

#  note end token can have NO leading whitespace
print $heredoc;

print line:

    print "line", "\n";

use data dumper for complex data, print to standard error log

    use Data::Dumper;
    print STDERR Data::Dumper::Dumper($node),"\n";

regex substitution

    # replace all words
    $sentence =~ s/london/London/g;

no match
 
    if ( $string !~ m/whatever/ ) {
        # it's not there
    }

regex match text, save to var

    # NOTE: $1 is a global var, may not be reset in a loop
    # () defines match

    # NOTE: =~ syntax seems backwards to me, but remember !~

    $string =~ m/whatever(sought_text)whatever2/;
    $soughtText = $1;


perl function, with variable

    # look ma, no args
    # everything is passed along the special @_ variable
    sub parse_layout {
      my $text = shift;

    }

    function rule of thumb:
        avoid long arg list.
        avoid referencing global data
        ideally, make all functions accept/return 1 hashref argument

if else

        if ( $line =~ /^#/ ) {
            # begins with comment;
        } elsif ( $line =~ /^\s*$/ ) {
            $endgroup = 1;
        } else {
            #data line;
        }

    comparison

        ==  != > < <= >=    for numbers only!
        eq, ne                for strings only!


    operators

        &&    and
        ||    or
        !    not

perl split string

    my $info = "part:part:part:part";
    my @parts = split(/:/, $info);

remove trailing newline, if it's there

    chomp();

trim

    sub trim {
        my $s = shift;
        $s =~ s/^\s+//;
        $s =~ s/\s+$//;
        return $s;
    }


define array/hash

    # actual named variables
    my @coins = ("Quarter","Dime","Nickel");
    my %account = ('username' => 'jimmyboy', 'password' => 's3cret!');


    # !!!! WARNING !!!!

    # perl doesn't really have a low-level concept of array like you might expect
    # for any complex array manipulation, use array/hash *pointers* instead (below)
    # unlike arrays, these can be assigned to another variable
    # or redefined in a loop
    # the pointers will work more like the array/hash in other languages

    NOTE: perl array "weirdness" as compared to php
    http://www.webreference.com/programming/perl/nested/index.html
    http://docstore.mik.ua/orelly/perl4/prog/ch09_01.htm


define array/hash pointers (what you should use)

    arrays are handled a bit differently than in php
    arrays loop by ref by default


    array reference

        my $array = [];

    hash reference

        my $hash = {};



    create from existing array/hash


        $aref = \@array;         # $aref now holds a reference to @array
        $href = \%hash;          # $href now holds a reference to %hash
        $sref = \$scalar;        # $sref now holds a reference to $scalar




define nested or complex data structure:
    grok:
        somewhat like javascript/python with {} []
        like php with =>

        my $VAR1 = {
                  'alpha' => [
                               123,
                               456
                             ],
                  'beta' => 'x'
                };


access array/hash pointer

    use $href-> to dereference


    # like c, can dereference pointer properties with ->


        $hashref->{key}
        $hashref->{'key'}   #quotes on keys optional
        $arrayref->[0]

    # alt syntax: use double $$ ... uglier

         $$hashref{'asdf'}
         $$arrayref[0]

dereference array ref to array

     @$ret

dereference array ref to hash
     %$ret

dereference field of a class:

    @{$user->{'Accounts'}}
    %{$user->{'Accounts'}}


loop over array

    foreach my $part ( @parts ) {
        print $part;
    }

loop over keys

    foreach my $key (  keys %hash ) {
        print $key;
    }


    NOTE: build a list of items, then perform operation on the list


passing refernce

    my %some_hash = ();
    return \%some_hash
 
    my %some_array ...
    return \@some_hash


sorting

    http://raleigh.pm.org/sorting.html

    case insensitive

        @s = sort {lc $a cmp lc $b} @a;

    element length

        @s = sort {lenth $a <=> length $b} @a;

    sub routine

        @s = sort mycriteria @a;
           sub mycriteria {
             my($aa) = $a =~ /(\d+)/;
             my($bb) = $b =~ /(\d+)/;

             sin($aa) <=> sin($bb) ||
             $aa*$aa <=> $bb*$bb;
           }


# two levels of sorting
# $a and $b are predefined

    sub inorder {
      $ACCT_SORTORDER{$user->{$a}{'TypeID'}} <=> $ACCT_SORTORDER{$user->{$b}{'TypeID'}}
        or
      $user->{$a}{'Nickname'} cmp $user->{$b}{'Nickname'};
    }

    my(@accounts) = sort inorder @{$user->{'Accounts'}};


try/catch exception

    here's the version of perl's try/catch

      eval {
        $response_doc = $parser->parse_string( $xml_str );
      };
      # catch parse exception            
      if($@) {
        # error
      }

      # reset $@ if calling again, this is global var
   

system call
    system "curl --basic --user $username:$password --data-ascii status='$message' http://twitter.com/statuses/update.json";
 
    # with backticks
    my $ret =
    `curl --basic --user $username:$password --data-ascii status='$message' http://twitter.com/statuses/update.json`;




file handling:


    mode    operand    create    truncate
    read    <      
    write    >        Y    Y
    append    >>        Y  
    Each of the above modes can also be prefixed with the + character to allow for simultaneous reading and writing.

    mode    operand    create    truncate
    read/write    +<      
    read/write    +>    Y    Y
    read/append    +>>    Y  


    # open file  for read
    open FILE, "
    As you might have guessed already if you just want read access you can skip the mode just as we did in the very first example above.

    Reading files

    If you want to read a text file line-by-line then you can do it as such:

    my @lines =
    The
    while (      print $_;
    }

    The $_ variable is automatically set for you to the contents of the current line. If you wish you may name your line variable instead:

    while (my $line =

    # release handle
    close FILE;


    # write to file
    open FILE, ">file.txt" or die $!;
    print FILE $str;
    close FILE;


perl oop

OOP perl is a little like Python

for more info:

    http://www.tutorialspoint.com/perl/perl_oo_perl.htm


    #!/usr/bin/perl

    package Person;

    sub new
    {
        my $class = shift;
        my $self = {
            _firstName => shift,
            _lastName  => shift,
            _ssn       => shift,
        };
        # Print all the values just for clarification.
        print "First Name is $self->{_firstName}\n";
        print "Last Name is $self->{_lastName}\n";
        print "SSN is $self->{_ssn}\n";
        bless $self, $class;
        return $self;
    }
    sub setFirstName {
        my ( $self, $firstName ) = @_;
        $self->{_firstName} = $firstName if defined($firstName);
        return $self->{_firstName};
    }

    sub getFirstName {
        my( $self ) = @_;
        return $self->{_firstName};
    }
    1;



# using
# use the source file, and call

    use Person;

    $object = new Person( "Mohammad", "Saleem", 23234345);
    # Get first name which is set using constructor.
    $firstName = $object->getFirstName();


# inherit

    our @ISA = qw(Person);    # inherits from Person



# CGI
#query parameters
# get/post parameters

    http://perldoc.perl.org/CGI.html


    use CGI;
    my $q = CGI->new;

        # Process an HTTP request
     @values  = $q->param('form_field');
     $fh      = $q->upload('file_field');
     $riddle  = $query->cookie('riddle_name');
     %answers = $query->cookie('answers');
    # Prepare various HTTP responses

    print $q->header();
    print $q->header('application/json');

    $cookie1 = $q->cookie(-name=>'riddle_name', -value=>"The Sphynx's Question");
    $cookie2 = $q->cookie(-name=>'answers', -value=>\%answers);
    print $q->header(
        -type    => 'image/gif',
        -expires => '+3d',
        -cookie  => [$cookie1,$cookie2]
        );
   print  $q->redirect('http://yoursite.com/your/page');

No comments: