Introduction to Perl
The "Practical Extraction and Report Language"
The "Pathologically Eclectic Rubbish Lister"
Perl
Creator: Larry Wall
Introduced: 1987
Open source
Comes standard on many UNIX/Linux systems
MacOS users are encouraged to use the
PerlBrew distribution of Perl.
-
Originally developed for text record manipulation
Used for system administration, web development, network programming, system exploit testing
Perl Uses
Perl Online Resources
Perl Execution
Programs typically given .pl extension
Executed with perl -w prog.pl
Or use shell script type line at top of Perl script
Using the “-w” is encouraged for debugging.
Perl Syntax (highlights)
More Perl Syntax
variables
$name = "fred"; # variables are dynamically typed
print "My name is ", $name, "\n";
variable scope
$name = "fred"; # This is global $name.
# Insert a block
{
my $name = "joe";
# This is local $name because of 'my'.
print "Block local \$name is $name\n";
# Using double quotes allows $name interpolation as
# part of the print statement. The backslashed $
# (\$name) suppresses variable interpolation.
}
print "Global \$name is ", $name, "\n";
print "Please enter something interesting: \n";
$comment = <STDIN>;
print "You entered: $comment\n";
$ perl -w stdin_comment.pl < comment.txt
$ echo "The ripest fruit falls first." | perl -w stdin_comment.pl
# If you have the fortune command installed ...
$ fortune | perl -w stdin_comment.pl
chomp() and chop()
print "Enter a five letter word guess, preferably \"Yoink\": ";
$userguess = <STDIN>;
chomp($userguess);
# Removes trailing newline character only.
# Test this without the chomp statement.
$secretword = "Yoink";
print "The result of the comparison: ", $userguess eq $secretword, "\n";
# String comparison with 'eq' operator;
# returns empty string if strings not equal;
# returns 1 if strings equal.
string functions
print "Enter a string: ";
my $inpString = <STDIN>;
chomp($inpString); # Must do this, else length will return length + 1.
print "$inpString is ", length($inpString), " chars long.\n";
my $string = "Hello, World!";
my $lowercase = lc($string);
print "$lowercase\n";
my $string = "Hello, World!";
my $uppercase = uc($string);
print "$uppercase\n";
my $string = "Larry Wall Larry Wall";
my $substring = "Wall";
my $position = index($string, $substring);
print "$position\n"; # Output: 6
my $string = "Larry Wall Larry Wall";
my $substring = "Wall";
my $position = rindex($string, $substring);
print "$position\n"; # Output: 17
my $string = "Hello, World!";
my $substring = substr($string, 7, 5);
# Starting at position 7, extract 5 characters
print "$substring\n"; # Output: World
The die() controlled exit function
print "Enter a string to pass to die(): ";
chomp($string = <STDIN>);
die($string); # Outputs to STDERR, not STDOUT
print "This will not be printed.";
selection statements, familiar
if ( $number != 0 ) {
$result = 100 / $number;
}
if ( $password eq $guess ) {
print "Pass, friend.\n";
} else {
die "Go away, imposter!";
}
selection statements, elsif
if ( $password eq $guess ) {
print "Pass, friend.\n";
} elsif ( $password eq "Meh" } {
print "Meh!\n";
} else {
die "Go away, imposter!";
}
selection statements, unless
# Assuming $a is boolean
if ( not $a ) {
print "\$a is not true\n";
}
# can also be expressed...
unless ( $a ) {
print "\$a is not true\n";
}
reverse selection statements
if ($number == 0) {
die "Can't divide by 0";
}
die "Can't divide by 0" if $number == 0;
repetition structures
while, until, for, foreach, do..while, do..until
until ( $countdown <= 0 ) {
print "Counting down: $countdown\n";
$countdown--;
}
# "for each number in the list 1 through 10"
foreach $number ( 1 .. 10 ) {
print "The number is: $number\n";
}
while (<STDIN>)
while ( $var = <STDIN> ) {
print $var;
# Print each line of standard input.
}
while ( <STDIN> ) {
print $_;
}
lists
print( "Hello, ", "world", "\n" );
# 3 strings in a list being passed to print function
print( 123, 456, 789 );
foreach $number ( 1 .. 10 ) {
# ( 1 .. 10 ) creates the list of numbers from 1 to 10
qw/hello world good bye/
# creates a 4 word list
accessing list values
print( ( 'salt', 'vinegar', 'mustard', 'pepper' )[ 2 ] );
# output: mustard (count from zero)
my $month = 3;
print qw(
Jan Feb Mar
Apr May Jun
Jul Aug Sep
Oct Nov Dec
)[ $month ]
# output: Apr
accessing list "slices"
my $mone;
my $mtwo;
( $mone, $mtwo ) = ( 1, 3 );
my $m1;
my $m2;
my $m3;
( $m1, $m2, $m3 ) = qw(
Jan Feb Mar
Apr May Jun
Jul Aug Sep
Oct Nov Dec
)[ 2..4 ];
print $m1." ".$m2." ".$m3;
arrays
my @days = qw(Mon Tue Wed Thu Fri Sat Sun);
print @days, "\n";
# Output: MonTueWedThuFriSatSun
print "@days\n";
# Output: Mon Tue Wed Thu Fri Sat Sun
# By enclosing in "", have "stringified" @days
print $days[ 6 ], "\n";
# @days[ 6 ] can also be used, but see the warning at https://stackoverflow.com/a/53732305
array size in $#
my $i = 0;
while ( $i <= $#arrayName ) {
# Do something with $arrayName[ $i ] here
$i++;
}
for ( my $i = 0; $i <= $#arrayName; $i++ ) {
# Do something with $arrayName[ $i ] here
}
arrays with foreach
foreach my $i ( @arrayName ) {
# Does not use $#.
# Do something with $i here.
}
accessing array slices
my @days = qw(Mon Tue Wed Thu Fri Sat Sun);
my @longweekend = @days[ 4..6 ];
# Note use of @ instead of $ before days.
print "@longweekend\n";
# Output: Fri Sat Sun
array functions
my @count = ( 1..5 );
foreach $each ( reverse( @count ) ) {
print "$each...\n";
sleep 1;
}
my @unsorted = qw( Cohen Clapton Costello Rush ZZTop );
my @sorted = sort @unsorted;
my $hand;
my @pile = ( "letter", "newspaper", "bill", "notepad" );
print "You pick up something off the top of the pile.\n";
$hand = pop @pile;
# "notepad" is removed from end (top) of @pile
print "You now have a $hand in your hand,\n \
and the pile contains:\n@pile";
print "You now put something on your pile.\n";
push @pile, "statement";
# "statement" is added to the end (top) of @pile
print "Now the pile contains:\n@pile\n";
my @array = (); # nothing in array
unshift @array, "first";
print "Array is now: @array\n";
unshift @array, "second", "third";
print "Array is now: @array\n";
shift @array;
print "Array is now: @array\n";
# //unshift// adds elements, //shift// deletes elements
hashes
%where = (
Gary => "Dallas",
Lucy => "Austin",
Ian => "Houston",
Samantha => "Seattle"
);
hash element access
my $who = "Ian";
my %where = (
Gary => "Piscataway",
Lucy => "Hackensack",
Ian => "Mahwah",
Samantha => "Hoboken"
);
print "Gary lives in ", $where{Gary}, "\n";
print "$who lives in $where{$who}\n";
hash element adding/deleting
my %where = (
Gary => "Piscataway",
Lucy => "Hackensack",
Ian => "Mahwah",
Samantha => "Hoboken"
);
$where{Eva} = "Howell";
# We added a Eva => "Howell" key/value pair to the
# %where hash
delete $where{Gary};
# We deleted the Gary => "Piscataway" key/value pair
hash functions, iteration
# use 'keys' function to iterate through hash keys
foreach $who ( keys %where ) {
print "$who lives in $where{$who}\n";
}
# use 'values' function to iterate through hash values
foreach $town ( values %where ) {
print "someone lives in $town\n";
}
# use 'each' function to iterate through hash key/value
# pairs
my ($name, $town);
# an assignable list of variables
while ( ($name, $town) = each %where ) {
print "$name lives in $town\n";
}
hash functions, key existence
print "Gary exists in the hash!\n" if exists $where{Gary};
subroutines
sub example_subroutine {
...
# subroutine body
...
}
greet();
sub greet {
print "Hello, World!\n";
}
subroutines, arguments
greet( "Jim", "Bob", "Russ" );
# There isn't a set number of function arguments or a
# function "prototype" to speak of
sub greet {
foreach my $arg ( @_ ) {
print "Hello $arg!\n";
}
print "You're first, $_[ 0 ].\n";
print "You're second, $_[ 1 ].\n";
print "You're last, $_[ 2 ].\n";
}
subroutines, returns
my ($len1, $len2, $len3) = greet( "Jim", "Bob", "Russ" );
print "($len1, $len2, $len3)\n";
sub greet {
foreach my $arg ( @_ ) {
print "Hello $arg!\n";
}
return (length($_[0]), length($_[1]), length($_[2]));
# return a list of 3 ints
}
Perl and Regular Expressions
Perl and Regular Expressions (match, search/replace)
$var =~ m/regular expression/
# boolean (true if match, false if no match)
# can omit the "m": $var =~ /regular expression/
$var !~ m/regular expression/
# true if not a match, false if a match
$var =~ s/search re/replace re/
my $name = "Joseph";
$name =~ s/[sph]//; # delete first instance of s, p or h
print "$name\n";
$name =~ s/[sph]//g; # g -> delete every instance of s, p or h
print "$name\n";
Perl and Regular Expressions (split)
split /\s+/, $_;
# split the default variable, using one or more
# whitespaces
my $passwd = "jchung:x:1032:51:J. Chung, CS:/home/jchung:/bin/bash";
my @fields = split /:/, $passwd;
Perl and Regular Expressions (join)
my $last = "Jones";
my $first = "Bob";
my $name = join ", ", ($last, $first);
$ perl -w perlex5.pl cs498roster cs598roster
while (<>) {
print "text read: $_";
}
Perl Command Line Arguments w/ @ARGV
foreach my $arg ( @ARGV ) {
print $arg;
}
or
for ( my $i = 0; $i <= $#ARGV; $i++ ) {
print $ARGV[ $i ];
}
or
print "$_" foreach @ARGV; // Perl-speak
Perl Command Line Arguments w/ shift @ARGV
$ perl -w perlex6.pl --help
$ perl -w perlex6.pl --last cs498roster cs598roster
my $arg0 = shift @ARGV;
if ( $arg0 =~ /last/ ) ...
# Process all non-file command line args before we
# get to //while (<>)//
while (<>) { ...
Perl References
my %hash = (
apple => "crab",
pear => "asian"
);
my $hash_r = \%hash;
my %hash2 = %{$hash_r};
# Set new %hash2 contents from the hash that is
# referenced by $hash_r
Perl Objects
“…an object can be anything -- it really depends on what your application is. … If you're communicating with a remote computer via
FTP, you could make each connection to the remote server an object.”
Perl Objects and Modules Example
use strict;
use Net::FTP;
# This requires that FTP.pm be stored somewhere on the
# local system that Perl searches through for modules.
my $ftp = Net::FTP->new("rockhopper.monmouth.edu")
or die "Couldn't connect: $@\n";
# new() is a method of class Net::FTP; it's the
# constructor. $ftp is our FTP session object.
$ftp->login("anonymous");
# New::FTP->login() method
$ftp->cwd("/");
$ftp->get("index.php");
$ftp->close();
Perl Modules and @INC
@INC contains the system file system paths that the Perl interpreter looks through for modules such as
FTP.pm.
$ perl -V
...
@INC:
/etc/perl
/usr/local/lib/perl/5.8.8
/usr/local/share/perl/5.8.8
/usr/lib/perl5
/usr/share/perl5
/usr/lib/perl/5.8
/usr/share/perl/5.8
/usr/local/lib/site_perl
.
Perl Modules and CPAN
A module is a collection of subroutines (methods) and variables (attributes) that all work together to perform some set of tasks
The Comprehensive Perl Archive Network (
http://www.cpan.org) was put together to organize and share the large collection of prewritten Perl modules.
The CPAN module naming hierarchy places modules in categories such as Sort::Fields
, Sort::Versions
or subcategories such as LWP::Protocol::http
On disk, the modules would look like …/Sort/Fields.pm
, …/Sort/Versions.pm
For the LWP::Protocol::http
module, the full path to the module might be /usr/share/perl5/LWP/Protocol/http.pm
on a Linux system.
How to know if a Perl module is installed?
# If the following runs with no errors, it means the LWP::Simple module is installed.
perl -e "use LWP::Simple"
Perl Web Automation
Perl and System Commands
For portability, use Perl equivalents to system commands, such as Perl's chdir(), function instead of cd.
system( '/usr/games/fortune' );
my $sysdate = `date`;