Perl Syntax Notes
Snippets of Perl Syntax to Insert Where Needed
Contents
Here Documents
Top BottomHere Documents allow you to process a block of text as an array of strings. Each line is an element of the array until the defined terminator is reached. The terminator is specified by a string immeadiately following two less than signs ('<<'). The block of text defined will interpolate according to whether the terminator is single, double-quoted or back-tick quoted. If unquoted, the block will behave as though the terminator was double-quoted.
use strict;
use warnings;
use Getopt::Long;
my ($commands, $help);
GetOptions(help => \$help, commands => \$commands);
&usage() unless $commands;
print <<`DONE`;
df -h
uptime
uname -a
DONE
sub usage() {
print <<"EOF";
Description
\tThe System Administration Time-Saver
Synopsis
\t$0 -c
Options
\t$0 -h, --help\tPrints this message
\t$0 -c, --commands\tRuns the commands
EOF
exit;
}
The array of strings can be fed to print to provide multiline documentation, or used anywhere that an array of strings might be used:
use strict; use warnings; my @fruit = <<ENDFRUIT =~ m/(\S.*\S)/g; passion fruit avocado pear bannana kiwi fruit paw paw ENDFRUIT print "Found ", scalar(@fruit), " fruits\n";
Readline Operator
Top BottomThe readline operator '<>' only assigns to $_ if it is the only condition in a while loop. At the end of the file '<>' returns undef, so check for defined rather than truth if assigning the line read. In scalar context, returns the next line in the file: in array context returns each line as a list element. Use '$.' to check the number of lines read so far by the script.
use strict;
use warnings;
use FindBin qw($Bin); # assigns path of script to $Bin
for my $file ( glob("$Bin/*.pl") ) {
next unless open(INPUT, $file);
print "$.] $_" while <INPUT>;
$. = 0; #reset line number to zero for next file
}
Arrays
Top BottomThe last index of an array is held in the special variable $#arrayname. The last element of an array can therefore be accessed as $arrayname[$#arrayname]. However it is also possible to write $arrayname[-1]. An array can be truncated, or extended by specifying a value for $#arrayname.
An array slice is specified as @arrayname['list literal']. An array slice will behave as a list literal in scalar context: returning its last element rather than a count of elements.
use strict; use warnings; use Test::More qw/no_plan/; my @arr = qw(one two three four five six seven eight nine); ok(scalar(@arr) == 9, "Number of elements in array"); ok($#arr == 8, "Index of last element"); ok($arr[$#arr] eq 'nine', "Last element in array via \$\#"); ok($arr[-1] eq 'nine', "Last element in array via -1"); my @evens = @arr[1,3,5,7]; my $count = @evens; ok($count == 4, 'Array returns number of elements in scalar context'); my $last = @arr[1,3,5,7]; ok($last eq $evens[-1], 'Slice acts as a list literal in scalar context, returning last element'); my ($first, undef, undef, $second) = @arr[1..4]; ok($first eq $arr[1], 'Elements assigned in left-right order in list context'); ok($second eq $arr[4], 'Unwanted elements can be assigned to undef'); $#arr = 3; ok(scalar(@arr) == 4, "Truncate an array by assigning to \$\#");
Hashes
Top BottomHashes are prefixed with a '%' sign and initialised with a list:
%sounds = (cat => 'meow', dog => 'bark', pig => 'oink', goldfish => 'undef')
Values are accessed via keys:
print "The $animal says " . $sounds{$animal};
use keys, values or each to iterate a hash:
foreach $key (keys %hash) foreach $value (values %hash) while (($nextkey, $nextval) = each %hash)
Subroutines
Top BottomCalled by specifying their name, followed by a list of arguments:
@values = mysub (@args, @moreArgs);
The list of arguments can be empty, or omitted altogether, if the subroutine is defined before the call:
sub timefunc { return localtime() }
$timeval = timefunc;
The parentheses around the argument list can also be omitted if the the subroutine has been defined before the call:
@values = myfunc $first, $last;
Calling a subroutine with the '&' prefix but no argument list means is gets the current @_ argument list instead. This also happens when calling the subroutine with goto:
goto &mysub;
Named arguments can be provided to a subroutine using the '=>' notation when listing the arguments:
checkServer(name => 'server01', date => '-1', cols => 3);
sub checkServer {
%defaults = (name => 'pdc01, date => '-5');
#defaults get overwritten by argument list
%args = (%defaults, @_);
#another way to specify a default
$args{cols} = 5 unless exists $args{cols};
..
}
The calling context of a subroutine can be determined using the wantarray function:
use Carp;
sub variousReturns {
# Do some processing here
# true and defined
return @someArray if wantarray;
# false but defined
return $someScalar if defined(wantarray);
#false and not defined
carp "subroutine &variousReturns was called in void context" unless(defined(wantarray));
}
Carp::carp reports the location of the call. Warn would report the location within the subroutine where the error occurred
The caller function returns a list of values indicating:
- the package from which the current subroutine was called
- the name of the file containing the code the called the current subroutine
- the line in that file from which the current subroutine was called
- the name of the subroutine
- whether the subroutine was passed arguments
- the context in which the subroutine was called
- the actual source code that called the subroutine, but only if the call was part of an eval TEXT statement
- whether the subroutine was called as part of a require or use statement
Reference and referents
Top BottomTo create a reference use the unary '\' operator. References can be made to scalars, arrays, hashes, subroutines filehandles, patterns, typeglobs and other references. Use 'ref($myRef)' to determine type of a reference. Use the '->' operator to dereference a reference:
my $s = "A scalar value";
my @a = qw(a list of vaules);
my %h = (first => 1, second => 2, third => 3);
my ($slr_ref, $arr_ref, $hsh_ref, $sub_ref) =
(\$s, \@a, \%h, \&print_results);
$sub_ref->($slr_ref, $arr_ref, $hsh_ref, $sub_ref,);
($slr_ref, $arr_ref, $hsh_ref) = (\"Second scalar value",
[qw(another list of values)], {fourth => 4, fifth => 5, sixth => 6});
$sub_ref->($slr_ref, $arr_ref, $hsh_ref);
print "Slice an array reference[", join(":", @$arr_ref[1,2]), "]\n";
print "Using arrow operator to access \$arr_ref->[1]: [$arr_ref->[1]]\n";
print "Using arrow notation to access \$hsh_ref->{fourth}: [$hsh_ref->{fourth}]\n";
my $matrix = [
[1, 4, 7, 9],
[2, 5, 8, 11],
[3, 6, 9, 12],
];
print "Element {2,3} of matrix is [$matrix->[1][2]]\n";
my $people = {
John => { age => 60, height => 200, birthday => '1999-04-01'},
Jill => { height => 180, sex => 'female', age => ''},
Fred => { sex => 'male', telephone => '00234283434', height => 60},
};
print "John is ", $people->{John}{age}, " years old\n";
sub print_results() {
my @args = @_;
foreach my $arg (@args) {
if (ref($arg) eq 'SCALAR') { print "${$arg}\n" }
elsif (ref($arg) eq 'ARRAY') { print "@{$arg}\n" }
elsif (ref($arg) eq 'HASH') {
foreach my $key (keys %{$arg}) { print "$key => ${$arg}{$key}\n" }
}
elsif (ref($arg) eq 'CODE') { print "Got a subroutine reference\n" }
else { print $arg, "\n" }
}
}
Namespaces
Top BottomAll variables exist in a namespace which is either global (defined in a package) or lexical (declared with 'my').
A symbol table or package is a global hash containing entries for global variables. To use a package variable outside the package namespace, prefix the variable with the name of the package and a double colon, or use a 'package' declaration to switch back to the package's namespace. A package declaration changes the namespace until another package declaration is encountered, or until the end of the current enclosing block.
Lexical variables must be defined with 'my', do not belong to any package and are only directly accessible within the defining code block. Lexical variables cease to exist outside the defining block unless some other part of the program has a reference to it. Lexical variables are not destroyed until their reference count is 0.
Local Variables
Top BottomThe local function takes package variables and replaces their value until the end of the enclosing block. Subroutines called from within the block will see the temporary value of the variable.
Modules
Top BottomModules are stored in .pm files, begin with a package declaration and end with '1;'. Version can be stored in $VERSION. Use the module with a 'use lib' statement to identify the modules location, and a 'use ModuleName' corresponding to the modules filename. Include version number as 'use ModuleName 1.20;'. Whenever a module is loaded, the modules 'import' subroutine is called with the name of the module plus any argument list that appears at the end of the module call. The 'import' subroutine is rarely used in OO perl.
Autoload
Top BottomIf a non-existent package subroutine is called, perl will try to call the packages subroutine AUTOLOAD before issuing an error. AUTOLOAD is called with the argument list passed to the missing subroutine and the $AUTOLOAD variable is assigned the fully-qualified name of the missing subroutine.
# Do shell programming from perl
sub AUTOLOAD {
$AUTOLOAD =~ s/.*:://;
return `$AUTOLOAD @_`;
}
$network = ipconfig();
del('README.TXT');
Closures
Top BottomA closure is a subroutine that refers to one or more lexical variables declared outside the subroutines block. Lexical variables are scoped within their defining block: subroutines are not. Therefore lexical variables can be made accessible outside their defining block, via a subroutine defined within the block. The lexical variable can then be accessed outside its defining block via the subroutine. Closures allow you to set up variables that are private to the subroutines within the block defining the lexical variable:
{
my $locked;
sub lock { return 0 if $locked; $locked = 1};
sub unlock { $locked = 0}
}
lock or die "Resource already in use";
# do some stuff
unlock();
Closures can be used to implement encapsulation.
Typeglobs
Top BottomA typeglob allows you to refer to all the symbol table entries for a particular package identifier. A typeglob is prefix with a '*' to indicate that it refers to all other types. Typeglobs do not apply to lexical variables, since they do not have a named symbol table. Assigning *bar to *foo, makes foo an alias for bar, and typeglob assignment forms the basis for module import/export operations. Individual entries in a symbol table can be assigned to another another typeglob using a reference as the rvalue.
package main;
$var = "The rain in Spain";
@var = qw( The rain in Spain);
%var = qw(The rain in Spain);
*newvar = *var;
print "The scalar in var is: [", $var, "]\n";
print "The scalar in newvar is: [", $newvar, "]\n";
print(join ":", @newvar, "\n");
*var = \"The sun in England";
print "The scalar in var is: [", $var, "]\n";
print "The scalar in newvar is: [", $newvar, "]\n";
$typeglob_ref = \*var;
print "The scalar in typeglob_ref is: [", ${*$typeglob_ref}, "]\n";
$slr_ref = *$typeglob_ref{SCALAR};
print "The scalar in slr_ref is: [", $$slr_ref, "]\n";
Symbolic references
Top BottomA symbolic reference is a character string containing the name of a variable or subroutine in a packages symbol table
package Utils;
sub formatter { print "Subroutine recieved '$_[0]' as first param\n"}
@formatter = qw(Yes that was lovely);
$formatter = ["no", "it", "wasn't"];
package main;
$symref = "Utils::formatter";
print "Here's the value of symref [$symref]\n";
print "Here's the symbolic reference to an array [@{$symref}] \n";
@{$symref}[0] = ${$symref}->[0];
print "After substituting from the scalar ref [", join(' ', @{$symref}), "]\n";
&{$symref}(${$symref}->[1]);
