Introduction to Perl

The following information was converted from an OpenOffice presentation I did for the Akron Linux Users Group in 2002.


What is Perl?


History


The Pros


The Cons


got Perl?


Comprehensive Perl Archive Network CPAN


The Perl Attitude

Or put another way...
A Perl scriptis "correct" if it gets the job done before your boss fires you.


Perl Oddities

Larry Wall - the lazy programmer

"A truly great computer programmer is lazy, impatient and full of hubris. Laziness drives one to work very hard to avoid future work for a future self."

Capitalization (Perl vs perl)

Perl Poetry

my @perl_experiences = ("Report generation",
                        "HTML generation",
                        "File backup and transfer",
                        "Source code generation",
                        "Data file conversion",
                        "Comma Separated Value conversion",
                        "Job scheduler",
                        "Test Bench stimulus generation",
                        "Generating PNG images",
                        "Accounting scripts");

Running Perl - Good Practices

When running the perl interpreter from the shell use the -w switch. This enables extra warnings to aid in development.

perl -w program.pl

The perl interpreter also has a "compile only" command line option. This option does not execute the script, but will catch syntax errors.

perl -c program.pl

Also use strict in the Perl source file, this forces predeclaration of variables. This should appear below the shebang line.

use strict;

Running Perl - More Good Practices

Call exit when done, and the Perl script should return a value.

Success

exit(0);

Failure (any positive integer)

exit(1);
exit(2);
...

Making Perl Scripts Executable

Put a shebang in the Perl source file as the first line, to allow Perl scripts to be run from the command line.

#!/usr/bin/perl -w 

Then give the appropriate groups execute privileges using chmod.

chmod u+x filename.pl

Line termination, Comments and POD

; Semicolon is line terminator
# is the EOL comment character
Plain Old Documentation (POD)
POD commands start with =
POD Converters
pod2text  - extract pod and format as text
pod2man   - extract pod and format as a manpage
pod2html  - extract pod and format as HTML
pod2latex - extract pod and convert to LaTeX

Command Line - ARGC, ARGV

# use the command line arguments
if (@ARGV==3) {
    $abs_prj_file = $ARGV[0];
    $path_date = $ARGV[1];
    $path_time = $ARGV[2];
    }
else {
    printf("usage is:\n");
    printf("copy_src.pl prj_file.prj datetime\n");
    exit(1);
    }

Operators (partiallist)

OperatorFunction
+ addition
% modulo
**exponent
. string concatination
& bit and
| bit or
^ bit xor
&&logical
= equality assignment
==numberic equality test
+=addition and reassignment
.=string concatination and reassignment
++bump or increment (pre and post)
eqstring equality


Variables - and the use of 'my'

If you are using 'use strict' you must scope variables with 'my'. Using 'my' within a subroutine declares the variable scope to the subroutine. Using 'my' outside subroutines make the variable global.

my $variable_name = "some value";

Scalar Variables


Scalar Examples

$age = 41;
$full_name = "George Whiteman";
$electron_mass = 9.10938188E-31;
$three_quarters = 3/4.0;
$literal_string = 'this is some text';
$substituted_string = "my name is $full_name";
$my_name = qq(George Whiteman);
$false_value = 0;
$another_false_value = 0.0;
$yet_another_false_value = "";
$a_true_value = "anything else";

Array Variables


Array Examples

# simple arrays
@a = ();                    # 0 elements - empty
@a = (23, 24, 25, 26, 33);  # 5 elements
@a = (23..26,33);           # same thing

# an array of strings
@a = ("debian", "redhat", "mandrake");

# samething - qw stands for quoted word
@a = qw(debian, redhat, mandrake);

# add another
@a = (@a, "suse");

# copy the array
@distro = @a;

# slice the array
($disto_user, @disto_commercial) = @a;

Hash Variables


Hash Examples

use strict;

my %part_number = ();
my $pn="";
my $desc="";

$part_number{10000} = "panhead 6-32";
$part_number{45390} = "panhead 8-32";
$part_number{10010} = "connector 23679";

while(($pn,$desc) = each(%part_number)) {
    if ($desc=~/panhead/) {
        printf("pn:%s desc:%s\n", $pn, $desc);
    }
}
exit(0);

Environment Variables

# get the value for the PATH environment variable
$temp_path = $ENV("PATH");

# force a new path
$ENV{"PATH"}="/bin:/usr/bin";

# execute some system command
system("$some_command");

# restore the old path
$ENV{"PATH"} = $temp_path;

Control Structure - if

# if statement with numbers
if ($number == 10) {
    print("number=$number\n")
    }

# if statement with strings
if ($os eq "dos") {
    system("format c:");
    }

Control Structure - if/elsif/else

# Perl has no switch statement.

if ($light eq "red") {
    execute_stop();
    }
elsif ($light eq "yellow") {
    execute_go_like_hell();
    }
elsif ($lighteq "green") {
    execute_go();
    }
else {
    printf("ERROR: unkown value for light: $light");
    exit(1);
    }

Control - for

# simple for loop
for ($i=0; $i<10; $i++) {
    printf("i:$i\n");
    }

# for loop accessing an array
@a=(1,2,5,6,8,34);
for ($i=0; $i<@a; $i++) {
    printf("a[%d]:%s\n", $i, $a[$i]);
    }

Control - foreach

# initialize an array of filenames
my @files=("file1.txt","file2.txt","file3.txt");

#process each element of the array
foreach $filename (@files) {
    printf("%s\n", $filename);
    }

Control - while

while($cmd ne "exit") {
    process($cmd);
    }

Strings - Concatination

# init some strings
$first_name = "George";
$last_name = "Whiteman";

# concatinate the strings
$full_name = $first_name . " " . $last_name;

# or use substitution
$full_name = "$first_name $last_name";

#print out the full name
printf("fullname: %40s", $full_name);

Strings - chomp(), chop()

Chomp removes the newline.

$user_input = ;
chomp($user_input);

Chop removes the last character

$a = 'exit;';
chop($a);

Strings - Splitting

# split the cmd string into tokens on whitespace
@token = split(/\s+/,$cmd);

#process the tokens
if ($token[0] eq "cmd1") {
    process_cmd1();
    }
elsif ($token[1] eq "cmd2") {
    if ($token[1] eq "opt1") {
        process_cmd2($token[1]);
        }
    }
else {
    printf("ERROR:unknown command");
     }

Strings - Joining

join() is the oposite of split()
my $delimiter = ",";
my @fields = ("larry","curly","moe");
$csv_line = join($delimiter, @fields);
printf("%s\n", $csv_line);

Strings - index(), rindex()

index() returns the location of the substring starting from the left
rindex()returns the location of the substring starting from the right
# match the postion of the substrings
my $a = "this is the end my friend";
my $b = index($a,"end");
my $c = rindex($a,"end");
printf("a:%s b:%d c:%d\n",$a,$b,$c);

Strings - substr()

# get a substring from a string
$the_str = "this is a string";
$start_pos = 5;
$n_chr = 2;
$is = substr($the_str, $start_pos, $n_chr);
printf("the definition of is is: %s\n", $is);

Strings - repeating

# generate a separator
printf("%s\n", "#" . ("-"x77));

Array - push(), pop()

# push data at the end of the array
push(@a, $another_value);
# pop data from the end of the array
$last_element = pop(@a);
# unshift data to the start of the array
unshift(@a, $another_value);
# shift data from the start of the array
$first_element = shift(@a);

Array - reverse(), sort()

# reverse an array
@reversed_array = reverse(@normal_array);
# sort an array
@sorted_array = sort(@unsorted_array);

Basic Input - STDIN

Getting input from <STDIN>

# get input from the user
my $response = "";
while($response ne "quit") {
    $response=;
    chomp($response);
    printf("%s\n",$response);
    }
exit(0);

Basic Output - printf()

printf() is much like the C language
use strict;

my $pi=3.1415927;
my $c = 3.0e8;
my $i=5;
my $name="George";

printf("%d\n", $i);
printf("%06d\n", $i);
printf("%5.2f\n", $pi);
printf("%d\n", $pi);
printf("%s\n", $c);
printf("%3.1f\n", $c);
printf("%3.1e\n", $c);
printf("%-40s\n", $name);
printf("%40s\n", $name);

Files and Directories - chdir, mkdir

Changing directories
my $dir_name = "/home/gwhiteman/perl/training";
chdir($dir_name) || die "cannot change to $dir_name($!)";
Making directories
my $dir_name = "/home/gwhit/perl/training";
mkdir($dir_name) || die "cannot change to $dir_name($!)";

Files and Directories - unlink()

Removing a set of files
# setup the filenames
my $file_dir = "/home/gwhiteman/perl/training";
my @files = ("file1.txt", "file2.txt", "file3.txt");
my $file_abs = "";

#process each element of the array
for $filename (@files) {
    $file_abs = $file_dir . "/" . $filename;
    printf "INFO: removing $file_abs\n";
    unlink($file_abs);
    }

Files and Directories - rename()

Renaming a file
# setup the filenames
$src_file = "/home/gwhiteman/perl/training/file1.txt";
$dst_file = "/home/gwhiteman/perl/training/file2.txt";
# do the rename
rename($src_file, $dst_file);

Files and Directories - Directory?

Detecting if a directory exists
# see if it exists and is a directory
if (-e $dirname && -d $dirname) {
    printf("INFO: %s already exists\n");
    }
#if not, create it
else {
    mkdir($dirname, 0755);
    }

Files and Directories - Executable?

Detecting if a file is executable
# test to see if the file is executable
if (-e $filename && -x $filename){
    system($filename);
    }
else {
    printf("ERROR: %s not executed\n", $filename);
    }

File Input

#!/usr/bin/perl -w
use strict;
my $in_file = "test1.txt";
my $current_line = "";
my $line_cnt = 1;
# open the file
open(INFILE, "$in_file") || die "Couldn't open file: $!";

#read the file in line by line
while() {
    $current_line = $_;
    chomp($current_line);
    printf("%08d %s\n", $line_cnt, $current_line);
    $line_cnt++;
    }
# close the file
close(IN_FILE);
exit(0);

File Output

#!/usr/bin/perl -w
use strict;

my $out_file = "hello_world.txt";
open(OUTFILE, ">$out_file") || die "Couldn't open file: $!";
printf OUTFILE ("Hello, world!\n");
close(OUTFILE);
exit(0);

Formatted Output - format

use strict;
my $first_name = "George";
my $last_name = "Whiteman";
my $email = "gwhiteman\@austin.rr.com";
write;
exit(0);
format STDOUT =@<<<<<<<<<@<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<$first_name,$last_name,$email.

Regular Expressions - Pattern Substitution

# substitute first occurance
$a=~s/search/replace/;

# substitute all occurances
$a=~s/search/replace/g;

Regular Expressions - Pattern Matching

if ($cmd=~/^doit/) {
    doit();
    }
else {
    dontdoit();
    }

Builtin Variables

VariableUsage
$$current process PID
$.input line number
$/input record separator(\n)
$,output field separator for print
$\output record separator (none)
$!system error message (related to $ERRNO)
$[first element index number (0)
$^operating system name
@INClibrary directories (require, use)
@ARGVcommand line args list
%ENVenvironment variables

Functions - Passing Scalars as Arguments

use strict;
my $result;

$result = add3(1,2,3);
printf("%s\n", $result);
exit(0);

sub add3 {
    my($a, $b, $c)=@_;
    return($a + $b + $c);
    }

Functions - Passing Arrays as Arguments

use strict;
my @data=(1,2,3,4,5,6);
my $result;

$result = addn(@data);
printf("%s\n", $result);
exit(0);

sub addn {
    my(@a) = @_;
    my $sum = 0;
    my $value;
    foreach $value (@a) {
        $sum += $value;
        }
    return $sum;
    }

Modules - Available from CPAN


Reference Books


Other Presentations