Академический Документы
Профессиональный Документы
Культура Документы
Table of Contents
What is Perl? 5
Where to Find Perl 6
What is CPAN? 7
Documentation 7
Perl Scripts 9
Print Functions 10
Literals 12
Quoting Rules 15
Here Documents 17
Variables 23
Naming Conventions 23
Scope and Package 23
Scalars 26
Assigning a value to a Scalar Variable 26
The $_ scalar variable 27
Arrays 28
Array slices 30
Some Array Functions 31
Associative Arrays (Hashes) 39
Reading From STDIN 41
<STDIN> Standard Input 41
Special Hashes 43
The %SIG Hash (Handling Signals) 44
Operators 49
Precedence and Associativity 49
Arithmetic Operators 51
Assignment Operators 51
Relational Operators 52
Equality Operators 55
Logical Operators 58
Autoincrement and Autodecrement Operators 59
String Operators 60
Range Operator 62
Generating Random Numbers 62
Pattern Matching 79
Simple Statements and Modifiers 79
Matching and Substitution Operations 82
The match operator 82
The substitution operator 83
Pattern Matching Operators 87
The RE Metacharacters 89
The Dot 92
Character Sets 94
Metasymbols to Represent Single Characters 95
Quantifiers ( * + ? ) 96
Alternation 97
Grouping 98
Subroutines 121
Arguments/Parameters 124
The Return Statement 127
Packages 128
The Symbol Table 129
Using the strict Pragma in Packages 132
The Standard Perl Library 134
Using a Perl5 Module from the Standard Perl Library 136
Objects 159
Methods 162
Destructors and Garbage Collection 169
Inheritance 170
Documenting Modules 175
Pod Files 175
Using the Expect.pm Module from CPAN 188
Using a Juniper Library 194
Perl Debugger 218
Module 1
Getting with it Syntactically
1.1 What is Perl?
• Perl stands for Practical Extraction and Report Language. Perl is an inter-
preted language, combining all the best features of the Shell, C, awk, grep,
and sed. It is used for extracting text from files, system administration
chores, and report writing.
• Perl was written by Larry Wall and released to the net in 1989. It has been
through two major revisions and is currently version Perl 5.8.8.
• The main distribution point for Perl is CPAN, the Comprehensive Perl
Archive Network at www.perl.com or www.perl.org. The main ftp site is
ftp.funet.fi (128.214.248.6).
• CPAN contains all the free Perl material you will ever need, including
documentation, faqs, scripts, binary distributions and source code, and
announcements. CPAN is mirrored all over the world and you can find the
nearest mirror at:
http://www.perl.com/CPAN
http://www.cpan.org
• CPAN is the place you will go if you want to find modules to help you
with your work. The CPAN search engine will let you find modules under
a large number of categories.
1.4 Documentation
• The standard Perl distribution comes with complete online documentation
called man pages, stemming from the Unix man pages (manual pages) pro-
viding help for all the standard utilities. Perl has divided its man pages into
categories. If you type at your command line prompt:
man perl
• To get a specific category, e.g. help on how to use Perl’s regular expres-
sions, type:
man perlre
1. Programming Perl, O’Reilly, Larry Wall, Tom Christianson & Jon Orwant, 3rd Edition, July 2000, p. 547.
• If you want to find out how a builtin function works, use the -f option fol-
lowed by the name of the function, as follows:
perldoc -f print
perldoc -f localtime
• If you are trying to find out how a particular library module works, you
can use the perldoc command to get the documentation. For example, if you
want to know about the CGI.pm module, type at the command line:
perldoc CGI
The documentation for the CGI.pm module will be displayed, and if you
type:
perldoc English
Example 1.1
$ cat first.plx
1 #!/usr/bin/perl
2 # My first try at perl
3 print “Hello to you and yours!\n”;
7 $ first.plx
8 Hello to you and yours!
• To run the script without using the #! line or chmod, give the perl script
name as an argument to the perl interpreter as follows:
$ perl first.plx
Example 1.2
Example 1.3
Example 1.4
( The Script )
#!/usr/bin/perl
1 printf “Hello to you and yours %s!\n”,”Sam McGoo”;
2 printf “The number in decimal is %d\n”, 45;
3 printf “The formatted number is |%10d|\n”, 100;
4 printf “Left justified the number is |%–10d|\n”,100;
5 printf “The number in octal is %o\n”,15;
6 printf “The number in hex is %x\n”, 15;
7 printf “The floating point number is |%8f|\n”, 15;
8 printf “The formatted floating point number is |%8.2f|\n”, 14.3456;
9 printf “The character is %c\n”,65;
10printf “The number in scientific notation is %e.\n”, 15.25;
11 printf"The binary value is %b\n", 0b1110;
12 printf"The binary value is %b\n", 15;
( The Output )
1 Hello to you and yours Sam McGoo!
2 The number in decimal is 45
3 The formatted number is | 100|
4 Left justified the number is |100 |
5 The number in octal is 17
6 The number in hex is f
7 The floating point number is |15.00000|
8 The formatted floating point number is | 14.35|
9 The character is A.
10The number in scientific notation is1.525000e+01.
11The binary value is 1110
12 The binary value is 1111
1.7 Literals
1.7.1 Numeric Literals
Example 1.5
12345 integer
23.45 float
.234E–2 scientific notation
0x456fff hexadecimal
0777 octal
0b111 binary (Perl 5.6)
Example 1.6
(The Script )
#!/usr/bin/perl
# Program to illustrate printing literals
1 print “The price is \$”,100, ”.\n”;
2 print “The number is ”,0777,”.\n”;
3 print “The number is ”,0xAbcF,”.\n”;
4 print “The unformatted number is ”, 14.56, ”.\n”;
5 printf “The formatted number is %f\n”, 14.56;
6 printf “The formatted number is %.2f\n”, 14.56;
7 print "The binary value 1110 is ", 0b1110, ".\n";
( Output )
1 The price is $100.
2 The number is 511.
3 The number is 43983.
4 The unformatted number is 14.56.
5 The formatted number is 14.560000
6 The formatted number is 14.56
7 The binary value 1110 is 14.
• Strings containing string literals are delimited by double quotes for back-
slash and variable substitution.
\t tab
\n newline
\r return
\f form feed
\b backspace
\a alarm
\e escape
\033 octal character
\xff hexadecimal character
\c[ control character
\l next character lower case
\u next character upper case
\L lower case until \E
\U upper case until \E
\Q backslash all following non-alphanumeric characters until \E is found
\E ends upper or lower case conversion started with \L or \U or \Q
\\ backslash
Example 1.7
(In Script)
1 #!/usr/bin/perl
2 print “***\tIn double quotes\t***\n”; # backslash interpretation
3 print ’%%%\t\tIn single quotes\t\t%%%\n’; # All characters are printed as literals
4 print “\n”;
(Output)
1 *** In double quotes ***
2 %%%\t\tIn single quotes\t\t%%%\n
Example 1.8
(In Script)
1 print “\a\t\tThe \Unumber\E \LIS\E ”,0777,”.\n”;
2 # Alarm followed by 2 tabs, the string “The”, the string “number” to be printed
#in upper case, the string “is” to be printed in lower case, the decimal value for
# octal 0777, and the newline character.
(Output)
1 (BEEP) The NUMBER is 511.
_ _DATA_ _ Also represents the logical end of the script; used with
<DATA> filehandle so that text can be read from the
script rather than from an external file.
Example 1.9
(In Script)
#!/usr/bin/perl
1 # Program to test special literals
2 print ”We are on line number ”, __LINE__, ”.\n”;
3 print ”The name of this file is ”,__FILE__ ,”.\n”;
4 __END__
And this stuff is just a bunch of chitter–chatter that is to be ignored by perl.
The __END__ literal is like cntrl–d or \004. ( See –x switch ).
(Output)
2 We are on line number 3.
3 The name of this file is literals.sp.
Example 1.10
(The Script)
#!/usr/bin/perl
# Program, named literals.perl2, written to test special literal __DATA_
1print <DATA>;
2__DATA__
This line will be printed.
And so will this one.
Output:
This line will be printed.
And so will this one.
1.7.5 Words
• Words consist of alphanumeric characters and underline
• Words must start with an alphanumeric character.
• If all lowercase, a word could conflict with future reserved words. A word
that has no other meaning to Perl will be treated as though it were enclosed
in single quotes.
• If the first word after print is not quoted, Perl treats it as a filehandle; there-
fore the filehandle, STDOUT, must be placed after print.
• As a rule of thumb, surround any bare words with either a pair of single or
double quotes.
Example 1.11
(The Script )
#!/usr/bin/perl
1 print ’She cried, ”I can\’t help you!”’,“\n”; # Clumsy
2 print qq/She cried, "I can’t help you!"\n/; # qq for double quotes
3 print qq/I need $5.00\n/; # Really need single quotes for a literal dollar sign to
# print
4 print q/I need $5.00\n/; # What about backslash interpretation?
print ”\n”;
5 print q/I need $5.00/,”\n”;
6 print q!I need $5.00!,”\n”;
7 print ”The present working directory is ”, ‘pwd‘;
8 print qq/Today is /, qx/date/;
9 print ”The hour is ”, qx{date +%H};
10print qq/Hello.\n/;
(The Output )
1 She cried, “I can’t help you!”
2 She cried, “I can’t help you!”
3 I need .00
4 I need $5.00\n
5 I need $5.00
6 I need $5.00
7 The present working directory is /home/jody/ellie/perl
8 Today is Fri Apr 20 17:05:37 PDT 2008
9 The hour is 17
10Hello.
Example 1.12
( The Script )
#!/usr/bin/perl
1 $name="Ellie";
2 print <<EOF; # The following text is treated as if surrounded by double quotes
3 \t\tHello there $name.
4 How are you doing today?
5 \UThere isn't much going on here\n.
6 EOF
11 print << x 4; # prints the line 4 times. Text must end in a blank line.
12Christmas is coming!
( Output )
3 Hello there Ellie.
4 How are you doing today?
5 THERE ISN'T MUCH GOING ON HERE.
Example 1.13
#!/bin/perl
# The HTML tags are embedded in the here document to avoid using
# multiple print statements
1 print <<EOF; # here document in a CGI script
2 Content-type: text/html
3 <HTML><HEAD><TITLE>Town Crier</TITLE></HEAD>
4 <H1><CENTER>Hear ye, hear ye, Sir Richard cometh!!</CENTER></H1>
5 </HTML>
6 EOF
Exercise 1
Getting with it Syntactically
1. At the command line prompt, write a Perl statement that will print:
Hello world!!
Welcome to Perl Programming.
2. Execute a Perl command that will display the version and patch informa-
tion of the Perl distribution you are currently using.
3. Write a Perl script called ”literals.plx” that will print the following (See
next page):
Note: The words PERL SCRIPT and NUMBER are capitalized by using
string literal escape sequences.
What command–line option would you use to check the syntax of your
script?
$ chmod +x literals.plx
$ literals
Today is Wed Oct 18 12:58:04 PDT 2007
The name of this PERL SCRIPT is literals.
Hello. The number we will examine is 125.5.
The NUMBER in decimal is 125.
The following number is taking up 20 spaces and is right justified.
| 125|
The number in hex is 7d
The number in octal is 175
The number in scientific notation is 1.255000e+02
The unformatted number is 125.500000
The formatted number is 125.50
My boss just said, ”Can’t you loan me $12.50 for my lunch?”
I flatly said, ”No way!”.
Good–bye (Makes a beep sound)
Module 2
The Funny Characters
2.1 Variables
• Scalars
• Arrays
• Associative Arrays
Package main
scalar array hash
S e pa r a t e N a m e s pa c e s f o r Var i a b l e s
Example 2.1
(The Script)
#!/usr/bin/perl
1 $salary=50000; # Scalar assignment
2 @months=qw(Mar Apr May); # Array
3 %states=( # Associative array assignment in Perl 5
4 ”CA” => ”California”,
5 ”ME” => ”Maine”,
6 ”MT” => ”Montana”,
);
7 print ”$salary\n”;
8 print ”@months\n”;
9 print %states, ”\n”;
10print ”\n\n$months[0] and $months[1]\n”;
11print ”$states{’CA’} and $states{’MT’}\n”;
print ”\n”;
12print $x + 3, ”\n”; # Context is numeric; initial value is 0
print ”\n”;
13print ”***$name***\n”; # Context is string; initial value is null
(The Output)
7 50000
8 Mar Apr May
9 MTMontanaMEMaineCACalifornia
12 3
13 ******
2.3 Scalars
• A scalar variable holds a single value and is preceded by a $ (dollar sign).
• The scalar holds a string or number value.
• The chop function chops off the last character of a scalar variable.
• The Perl5 chomp function chops off the character that is designated as the
end of line character, a newline by default. The special Perl variable, $/,
holds the newline value.
6 print “$num\n”;
7 print $name;
8 chomp $name; # removes the newline
9 print “I need \$$money\n”;
10print qq/$name gave me \$$money.\n/;
11print qq/The time is $now/;
(The Output)
6 5
7 John Smith
9 I need $125.75
10 John Smith gave me $125.75.
11 The time is Tue Sep 10 12:34:41 PDT 2005
Example 2.3
1 $_ = "Mary Jones";
2 print; # same as print "$_";
(Output)
Mary Jones
Example 2.4
(The Script)
#!/home/perl/perl
# Program: loop.file
open(FH, "empnames.txt") ;
1 while(<FH>){ # Each line is read from the file, one at a time, and stored in $_
2 print;
}
2.6 Arrays
• Arrays are named lists; lists are an ordered sequence of scalars.
• The name of the array starts with a @ sign.
• If the array is initialized, the elements are enclosed in parentheses and each
element is separated by a comma.
• Lists are parenthesized due to the lower precedence of the comma opera-
tor over the assignment operator.
• Subscripts start at zero. $array[0] is the first element of @array. A neg-
ative subscript starts from the end of the array; e.g. $array[-1] is the last ele-
ment and $array[-2] is the last element.
• Elements in an array are simply scalars, and must be preceded with a $
sign.
• The .. operator, the range operator, returns an array of values starting from
the left value to the right value in increments of one.
• If an array is assigned to a scalar, the value of the scalar is the number
of elements in the array. If the array is prefixed with $#, the resulting value
is the number of the last subscript.
• An array without a name is called an anonymous array.
(Perl5)
• The qw construct allows you to list array elements as singly quoted words.
Example 2.5
( The Script )
#!/usr/bin/perl
1 @names=(‘John’, ‘Joe’, ‘Jake’);
2 print @names, “\n”; # prints without the separator ( See join )
3 print “Hi $names[0], $names[1], and $names[2]!\n”;
( The Output )
2 JohnJoeJake
3 Hi John, Joe, and Jake!
5 There are 3 elements in the @names array.
6 The last element of the array is Jake.
7 The number of the last subscript in the array is 2.
9 The first element of the @fruit array is apples; the second element is pears.
10 Starting at the end of the array: plums pears
Example 2.6
( The Script )
#!/usr/bin/perl
1 @names=(’Tom’, ’Dick’, ’Harry’, ’Pete’);
2 @pal=@names[1,2,3]; # slice
3 print ”@pal\n\n”;
( The Output )
3 Dick Harry Pete
5 Tom Dick Harry
• The pop function pops off and returns the last element of an array.
Format:
pop(ARRAY)
pop ARRAY
Example 2.7
(In Script)
#!/usr//bin/perl
# Script: pop_function
1 @names=(“Bob”, “Dan”, “Tom”, “Guy”);
2 print "@names\n”;
3 print pop(@names); #pops off last element of the array
4 print ”\n@names\n”;
(The Output)
2 Bob Dan Tom Guy
3 Guy
4 Bob Dan Tom
Before After
Bob Dan Tom Guy pop off the end Bob Dan Tom
• The push function pushes values onto the end of an array, increasing the
length of the array.
Format:
push(ARRAY, LIST)
Example 2.8
(In Script)
#!/usr//bin/perl
# Script: push_function
1 @ names=(“Bob”, “Dan”, “Tom”, “Guy”);
2 push(@names, Jim, Joseph, Archie);
3 print “@names \n”;
(The Output)
3 Bob Dan Tom Guy Jim Joseph Archie
Before After
push on
Bob Dan Tom Guy
to the
Bob Dan Tom Guy Jim Joseph Archie
end
• The shift function shifts off and returns the first element of an array,
decreasing the size of the array by one element.
If ARRAY is omitted, then the ARGV array is shifted, and if in a subroutine,
the @_ array is shifted.
Format:
shift(ARRAY)
shift ARRAY
shift
Example 2.9
(The Script)
#!/usr/bin/perl
# Script: shift_function
1 @names=(“Bob”, “Dan”, “Tom”, “Guy”);
2 shift @names; # shifts the @names array one to the left
3 print "@names\n”;
4 $num=1;
(The Output)
3 DanTom Guy
Before After
Bob Dan Tom Guy shift off the beginning Dan Tom Guy
Format:
unshift(ARRAY, LIST)
Example 2.10
(In Script)
# Script: unshift_function
1 @names=( Jody, Bert, Tom ) ;
2 unshift(@names, Liz, Daniel);
3 print “@names\n”;
(The Output)
3 Liz Daniel Jody Bert Tom
Before After
Jody Bert Tom prepend to the beginning Liz Daniel Jody Bert Tom
Example 2.11
(The Script)
#!/usr/bin/perl
1 $string=“Dane Leo Starkey”;
2 @names=split(‘ ’,$string);
3 print “The first name is $names[0].\n”;
4 print “The second name is $names[1].\n”;
(The Output)
3 The first name is Dane.
4 The second name is Leo.
news
ingres
audit
Example 2.12
The list returned by split in this example has no name. It is called an anonymous
list. Because each of the items in the list are named variables, it is easier to read
and manipulate the script’s data.
(The File)
$ cat datebook
Betty Boop:245–836–8357:635 Cutesy Lane, Hollywood, CA 91464:6/23/
23:14500
Igor Chevsky:385–375–8395:3567 Populus Place, Caldwell, NJ 23875:6/18/
68:23400
Norma Corder:397–857–2735:74 Pine Street, Dearborn, MI 23874:3/28/
45:245700
Jennifer Cowan:548–834–2348:583 Laurel Ave., Kingsville, TX 83745:10/1/
35:58900
Example 2.13
(The Script)
#!/usr/bin/perl
# This script loops through a file; each line is split using the colon as a separator.
# If the second argument to split is missing, the default is $_.
open(FH, "datebook.master");
1 while(<FH>) {
2 ($name,$phone,$address,$bd,$sal)=split(":") ;
3 print ”$name $phone\n”;
}
close(FH)
(The Output)
3 Betty Boop 245–836–8357
Igor Chevsky 385–375–8395
Norma Corder 397–857–2735
Jennifer Cowan 548–834–2348
Fred Fardbarkle 674–843–1385
• The join function joins the elements of an array into a single string and
separates each element of the array with a delimiter––opposite of split.
Often used after the split function has broken a string into array elements.
Format:
join(EXPR, LIST)
EXPR is the value of the delimiter that will separate the array elements.
LIST consists of the array elements.
Example 2.14
#!/usr/bin/perl
Script: join_function
1 $string= “Joe Blow:11/12/86:10 Main St.:Boston, MA:02530”;
2 ($name, $birth, $address)=split(":", $string);
3 print $name, “\n”;
4 print $birth,“\n”;
5 print $address,“\n”;
6 print join(“:”, $name, $birth, $address ), “\n”;
(The Output)
3 Joe Blow
4 11/12/86
5 10 Main St.
6 Joe Blow:11/12/86:10 Main St.
Format:
reverse(LIST)
reverse LIST
Example 2.15
(In Script)
#!/usr/bin/perl
#Script: reverse_function
1 @names=(“Bob”, “Dan”, “Tom”, “Guy”);
2 print “@names \n”;
3 @reversed=reverse(@names);
4 print join(“ ”, @reversed,“\n”);
(The Output)
2 Bob Dan Tom Guy
4 Guy Tom Dan Bob
Format:
splice ARRAY,OFFSET,LENGTH,LIST
splice ARRAY,OFFSET,LENGTH
splice ARRAY,OFFSET
splice ARRAY
Example 2.16
1 @colors=qw(red green blue yellow);
2 print "Array was: @colors.\n";
3 @return_value=splice(@colors,1,1);
4 print "New array: @colors.\n";
5 print "What was removed: @return_value.\n";
(Output)
2 Array was: red green blue yellow.
4 New array: red blue yellow.
5 What was removed: green.
7 Array was: red blue yellow.
9 New array: red blue purple.
Example 2.17
(In Script )
1 %department = (
2 ’Eng’ => ’Engineering’, # Eng is the key, Engineering is the value
3 ’M’ => ’Math’,
4 ’S’ => ’Science’,
5 ’CS’ => ’Computer Science’,
6 ’Ed’ => ’Education’,
7 );
8 $department = $department{“M”};
9 $school = $department{“Ed”};
10print “I work in the $department section\n” ;
11 print “Funds in the $school department are being cut.\n”;
12print qq/I’m currently enrolled a $department{CS} course.\n/;
13print qq/The department associative array looks like this:\n/;
14print %department, “\n”;
( The Output )
10 I work in the Math section
11 Funds in the Education department are being cut.
12 I’m currently enrolled a Computer Science course.
13 The department associative array looks like this:
14 EdEducationEngEngineeringSScienceMMathCSComputer Science
Example 2.18
(The Script)
#!/usr/bin/perl
# Script using built-in functions to get the keys and values from a hash
1 %department = (
Eng => ’Engineering’, # Eng is the key, Engineering is the value
M => ’Math’,
S => ’Science’,
CS => ’Computer Science’,
Ed => ’Education’,
);
2 @keylist = keys(%department); # The keys function returns a list of hash keys
3 print "@keylist\n";
(The Output)
3 Ed Eng S M CS
5 Education Engineering Science Math Computer Science
7 Ed - Education
Eng - Engineering
S - Science
M - Math
CS - Computer Science
Example 2.19
(In Script)
#!/usr/bin/perl
1 print “What is your name? ”;
2 $name = <STDIN> ; #set $name to the next line of input; can use <>
3 chomp($name); # Remove the newline.
4 print “$name, how are you?\n”;
(The Output)
1 What is your name? Santa Clause
4 Santa Clause, how are you?
• When reading input from STDIN, if the context is array, each line is read
with its newline and the whole line is treated as a single list item (single ele-
ment of the array).
• So that the program will stop accepting input, the user must press Ctrl-d
(^D).
Example 2.20
(The Script)
1 print ”Tell me everything about yourself.\n”;
2 @all = <STDIN>; # First line of input is assigned to $all[0], etc.
3 print @all;
4 print "$all[0]\n";
(The Output)
1 Tell me everything about yourself.
2 O.K. Let’s see. I was born a long time ago.
I was part of the hippy generation.
I have four children and two dogs.
I’m getting sick of talking about myself
^D (Ctrl d)
3 O.K. Let’s see. I was born a long time ago.
I was part of the hippy generation.
I have four children and two dogs.
I’m getting sick of talking about myself
4 O.K. Let’s see. I was born a long time ago.
Example 2.21
(The Script)
#!/usr/bin/perl
1 $course_number = 101;
2 print ”What is the name of course 101? ”;
3 chomp($course{$course_number} = <STDIN>);
4 print ”The course is $course{$course_number}.”;
(The Output)
2 What is the name of course 101? Intro Computer Science <-- user input
4 The course is Intro Computer Science.
• The %ENV hash contains the environment variables handed to Perl from
the parent process, e.g., a shell or a Web server.
• The key is the name of the environment variable, and the value is what
was assigned to it. If you change the value of %ENV, you will alter the envi-
ronment for your Perl script and any processes spawned from it, but not the
parent process. Environment variables play a significant roll in CGI Perl
scripts.
Example 2.22
(In Script)
#!/usr/bin/perl
1 foreach $key (keys(%ENV){
2 print "$key\n"; }
3 print "\nYour login name $ENV{'LOGNAME'}\n";
4 $pwd=$ENV{'PWD'};
5 print "\n", $pwd, "\n";
}
(Output)
OPENWINHOME
MANPATH
FONTPATH
LOGNAME
USER
TERMCAP
TERM
SHELL
PWD
HOME
• There are two general types of signals: those that cause termination of a
process and those that do not.
• Except for the SIGKILL and SIGSTOP signals, signals can be caught,
ignored, or generate an interrupt. These signals are defined in the file <sig-
nal.h>.
• The %SIG hash allows you to set signal handlers for signals. If, for exam-
ple, you press <Ctrl>-C when your program is running, that is a signal, iden-
tified by the name, SIGINT. (See UNIX manual pages for a complete list of
signals.)
• The default action of SIGINT is to interrupt your process. The signal han-
dler is a subroutine that is automatically called when a signal is sent to the
process. Normally, the handler is used to perform a clean-up operation or to
check some flag value before the script aborts. (All signal handlers are
assumed to be set in the main package.)
• The %SIG array only contains values for signals set within the Perl script.
Example 2.23
(In Script)
#!/usr/bin/perl
1 sub handler{
2 local($sig) = @_; # First argument is signal name
3 print "Caught SIG$sig -- shutting down\n";
exit(0);
}
4 $SIG{'INT'} = 'handler'; # Catch <Ctrl>-c
print "Here I am!\n";
5 sleep(10);
6 $SIG{'INT'}='DEFAULT';
7 $SIG{'INT'}='IGNORE'; < Program continues here >
Exercise 2
The Funny Characters
1. Write a script called foods that will create a list of your favorite five
foods. The list of foods will be stored in a scalar, each food separated by a
comma. Split the scalar and create an array.
2. Write a script called “elective” that will contain a hash (associative array).
a.The keys will be code numbers––2CPR2B, 1UNX1B, 3SH414,
4PL400.
b.The values will be course names, “C Language”, “Intro to UNIX”,
“Shell Programming”, “Perl Programming”.
c. Print the entire hash.
d. Ask the user to type the code number for the course he plans
to take this semester and print a line resembling the following:
You will be taking Shell Programming this semester.
What is the EDP number of the course you wish to take? 4pl400
The course you will be taking is ”Perl Programming”.
Module 3
Operator, operator...
3.1 Operators
3.2 Precedence and Associativity
• When an expression contains a number of operators and operands, and the
result of the operation is potentially ambiguous, the order of precedence and
associativity tells you how the compiler evaluates such an expression.
• Precedence refers to the way in which the operator binds to its operand.
The multiplication operator binds more tightly to its operands than the addi-
tion operator so it is of higher precedence, whereas the assignment operators
are low in precedence and thus bind loosely to their operand. 1
• Parentheses are of the highest precedence and are used to control the way
an expression is evaluated. When parentheses are nested, the expression
contained within the innermost set of parentheses is evaluated first.
• Associativity refers to the order in which an operator evaluates its oper-
ands, left to right, in no specified order, or right to left.
Example 3.1
(The Script)
1 $x = 5 + 4 * 12 / 4;
2 print "The result is $x\n";
3 $x = ( 5 + 4 ) * ( 12 / 4 );
4 print "The result is $x\n";
Output
2 The result is 17
4 The result is 27
Operator/Operands Function
$x + $y Addition
$x – $y Subtraction
$x * $y Multiplication
$x / $y Division
$x % $y Modulus
$x ** $y Exponentiation
Example 3.2
(The Script)
1 printf "%d\n", 4 * 5 / 2;
2 printf "%d\n", 5 ** 3;
3 printf "%d\n", 5 + 4 - 2 * 10;
4 printf "%d\n", (5 + 4 - 2 ) * 10;
5 printf "%d\n", 11 % 2;
Output
1 10
2 125
3 -11
4 70
5 1
Example 3.3
(The Script)
1 $name="Dan";
2 $line=”*”;
3 $x=0; # assign 0 to $x
4 $x += 3; # add 3 to $x; same as $x=$x+3
5 print “x=x+3 is $x \n”;
8 $x **= 2; # square x
9 print ”x squared is $x\n” ; #
10$x %= 3;
11 print ”The remainder of x/3 is $x\n”;
(The Output)
5 x=x+3 is 3
7 x=x–1 is 2
9 x squared is 4
11 The remainder of x/3 is 1
13 Danielle
15 **********
3.5.1 Numeric
Operator/Operands Function
3.5.2 String
Operator/Operands Function
Example 3.4
(The Script)
$x = 5;
$y = 4;
1 $result = $x > $y;
2 print "$result\n";
Output
2 1
4 0
String.
• The string relational operators evaluate their operands (strings) by com-
paring the ASCII value of each character in the first string to the correspond-
ing character in the second string. The comparison includes trailing
whitespace.
• If the first string contains a character that is of a higher or lower than
ASCII value than the corresponding character in the second string, the value
one is returned. Otherwise zero is returned.
Table 3.2 contains a list of relational string operators.
TABLE 3.3 Relational Operators and String Values
Operator ExampleMeaning
gt $str1 gt $str2$str1 is greater than $str2
ge $str1 ge $str2$str1 is greater than or equal to $str2
lt $str1 lt $str2$str1 is less than $str2
le $str1 le $str2$str1 is less than or equal to $str2
Example 3.5
(The Script)
1 $fruit1 = "pear";
2 $fruit2 = "peaR";
3 $result = $fruit1 gt $fruit2;
4 print "$result\n";
Output
4 1
6 0
Numeric.
Example 3.6
(The Script)
$x = 5;
$y = 4;
1 $result = $x == $y;
2 print "$result\n";
3 $result = $x != $y;
4 print "$result\n";
Output
2 0
4 1
6 1
8 1
String.
Example 3.7
(The Script)
$str1 = "A";
$str2 = "C";
1 $result = $str1 eq $str2;
print "$result\n";
Output
1 0
2 1
3 -1
4 1
6 0
Example 3.8
# Don’t use == when you should use eq!
1 $x = "yes";
2 $y = "no";
print "\nIs yes equal to no? If so, say 1; if not say 'null'.\n";
3 print "The result is: ",$x == $y,"\n"; # should be $x eq $y
Output
3 Is yes equal to no? If so, say 1; if not say 'null'.
The result is: 1
Operator/Operands Function
$num1 && $num2 $num2, if $num1 and $num2 are true.
$num1 || $num2 $num1, if $num1 is true or $num2 if $num2 is true.
! $num1 Not $num1; returns either 1 or the null string..
-----------------------------------------------------------------------------------
Example 3.9
(In Script)
#!/usr/bin/perl
1 # logical operators
2 $num1=50;
3 $num2=100;
4 $num3=0;
5 print $num1 && $num2, ”\n”; # could use $num1 and $num2
6 print $num1 && $num3, ”\n”;
7 print $num1 || $num3, ”\n”; # could use $num1 or $num2
8 print ! $num3, ”\n”; # could use not $num3
9 print !( $num1 && $num2),”\n”;
(The Output)
5 100
6 0
7 50
8 1
9
++$x Pre–increment
$x++ Post–increment
––$x Pre–decrement
$x–– Post–decrement
Example 3.10
(The Script)
#!/usr/bin/perl
1 $x=5; $y=0;
2 $y=++$x; #add one to $x first; then assign to $y
3 print ”Pre–increment:\n”;
4 print “y is $y\n”;
5 print “x is $x\n”;
6 print “–––––––––––––––––––––––\n”;
7 $x=5;
8 $y=0;
9 print ”Post–increment\n”;
10$y=$x++; # assign value in $x to $y; then add one to $x
11 print “y is $y\n”;
12print “x is $x\n”;
(The Output)
3 Pre–increment:
4 y is 6
5 x is 6
–––––––––––––––––––––––
9 Post–increment
10 y is 5
11 x is 6
Example 3.11
(The Script)
#!/usr/bin/perl
1 $x="pop";
2 $y="corn";
3 $z="*";
4 print $z x 10, "\n"; # print 10 stars
5 print $x . $y, "\n"; # concatenate "pop" and "corn"
6 print $z x 10, "\n"; # print 10 stars
7 print (($x . $y ." ") x 5 ); # concatenate "pop" and "corn" and print 5 times
8 print "\n";
9 print uc($x . $y), "!\n"; #convert string to uppercase
Output
4 **********
5 popcorn
6 **********
7 popcorn popcorn popcorn popcorn popcorn
9 POPCORN!
Example 3.12
(The Script)
#!/usr/bin/perl
1 $line=“Happy New Year”;
2 print substr($line, 6, 3),”\n”; # offset starts at zero
3 print index($line, “Year”),”\n”;
4 print substr($line, index($line, “Year”)),”\n”;
5 substr($line, 0, 0)=“Fred, ”;
6 print $line,”\n”;
7 substr($line, 0, 1)=“Ethel”;
8 print $line,“\n”;
9 print substr($line, –4);
10print uc ”have a wonderful year!!\n”;
11$string="I'll eat a tomato tomorrow.\n";
12 print rindex($string, tom), "\n";
(The Output)
2 New
3 10
4 Year
6 Fred, Happy New Year
8 Ethelred, Happy New Year
9 you!
10 HAVE A WONDERFUL YEAR!!
12 18
100 .. 200 A range operator, starting with 100 and going to 200, incrementing
by 1; e.g. 100, 101, 102 ... 199, 200
Example 3.13
Format:
rand(EXPR)
rand EXPR
rand
srand(EXPR)
srand EXPR
Example 3.14
(The Script)
#!/usr/bin/perl
1 $num=10;
2 srand(time|$$); # seed rand with the time or’ed to the pid of this process
3 while($num){ # srand not necessary in versions 5.004 and above
4 $lotto = int(rand(10)) + 1; # returns a random number between 1 and 10
5 print ”The random number is $lotto\n”;
sleep 3;
$num––;
}
(The Output)
The random number is 5
The random number is 5
The random number is 7
The random number is 8
The random number is 1
The random number is 5
The random number is 4
The random number is 4
The random number is 4
The random number is 6
Example 3.15
(The Script)
#!/usr/bin/perl
1 $x=5 ; # starting point in a range of numbers
2 $y=15; # ending point
3while(1){
4 print int(rand($y - $x + 1)) + $x , "\n";
5 sleep 1;
}
Output:
15
14
5
10
11
6
12
6
7
10
6
8
6
15
11
Do Exercise 3
Format:
if ( EXPR ) { BLOCK}
if ( EXPR ){ BLOCK} else{ BLOCK}
if ( EXPR ) { BLOCK} elsif ( EXPR ){ BLOCK }... else{ BLOCK}
unless ( EXPR ) { BLOCK }
unless ( EXPR ) { BLOCK } else { BLOCK }
unless ( EXPR ) { BLOCK} elsif ( EXPR ){ BLOCK }... else{ BLOCK}
Example 3.16
1 if ( $answer eq "yes" ){ print "Let’s move on!\n"; }
Example 3.17
(The Script)
#!/usr/bin/perl
# Script: cond_statement_ex1
2 while(<>){
3 ($name, $phone)=split(/:/);
4 unless ( $name eq ”Betty Boop” ){
5 print ”$name––$phone\n”;
6 }
7 }
Example 3.18
(The Script)
#!/usr/bin/perl
# Script: cond_statement_ex2
1 print ”What version of the operating system are you using? ”;
2 chomp($os=<STDIN>);
3 if ( $os > 2.2 ) { # Braces required always
print ”Most of the bugs have been worked out.\n”;
4 }
5 else { # Braces required always
print ”Expect some problems!\n”;
}
Example 3.19
(The Script)
#!/usr/bin/perl
#Script: cond_statement_ex3
1 $hour=‘date +%H‘; # Assign the output of the UNIX date command to $hour
2 if ( $hour >= 0 && $hour < 12 ){print ”Good–morning!\n”;}
3 elsif($hour == 12 ){print ”Lunch time.\n”;}
4 elsif($hour > 12 && $hour < 17 ){print ”Siesta time.\n”;}
5 else{print ”Goodnight. Sweet dreams.\n”;}
(The Output)
Siesta time.
switch (expression) {
case value1 :
/* statements */
break;
case value2 :
/* statements */
break;
case value3 :
/* statements */
break;
default:
/* statements */
break;
}
Example 3.20
1 use Switch;
print "What is your favorite color? ";
chomp($color=<STDIN>);
2 switch("$color"){
3 case "red" { print "Red hot peppers!\n"; }
case "blue" { print "I got a feeling called the blues.\n"; }
case "green" { print "How green my valley\n";}
case "yellow" { print "In my yellow submarine";}
4 else { print "$color is not in our list.\n";}
}
print "Execution continues here....\n";
(Output)
What is your favorite color? blue
I got a feeling called the blues.
Execution continues here....
3.14 Loops
• Loops are used to execute a segment of code repeatedly.
• Perls’s basic looping constructs are:
while
until
for
foreach
Format:
while ( EXPR ) {BLOCK}
Example 3.21
(The Script)
#!/usr/bin/perl
# Script: while_loop
1 $num=0; #initialize
2 while($num <= 10 ){ # test expression;
# loop quits when expression is false or 0
3 print “$num ”;
4 $num++; # update the loop variable $num; increment $num
}
5 print “\nOut of the loop.\n”;
(The Output)
0 1 2 3 4 5 6 7 8 9 10
Out of the loop.
1 $x=0;
2 do{ # block is executed before while expression is tested.
print $x;
$x++;
}while($x < 10);
Format:
until ( EXPR ) {Block}
Example 3.22
(The Script)
#! /usr/bin/perl
#Script: until_loop
1 $num=0; # initialize $num
2 until ($num == 10) { # test expression;
# loop quits when expression is true or non–0
3 print $num++, ” ”; # update the loop variable $num; increment $num
}
print ”\nOut of the loop.\n”;
(The Output)
0123456789
Out of the loop.
Format:
for(EXPR;EXPR;EXPR){BLOCK}
Example 3.23
(The Script)
#!/usr/bin/perl
#Script: for_loop
1 for($i=0;$i<10;$i++){ # initialize, test, and increment $i
2 print “$i ”;
}
3 print ”\nOut of the loop.\n”;
(The Output)
0123456789
Out of the loop.
Example 3.24
This example shows the differences between the for and while loops.
(The Script)
#!/usr/bin/perl
# Script: while_vs_for_loop
1 $count=1;#Initialize variables
2 $beers=10;
3 $remain=$beers;
4 $where=“on the shelf”;
5 while($count <= $beers) {
6 if($remain == 1){print “$remain bottle of beer $where $where ” ;}
7 else{ print “$remain bottles $where $where”;}
8 print “ Take one down and pass it all around.\n”;
9 print “Now ”, $beers – $count , ” bottles of beer $where!\n”;
10 if ( $count == 10 ){print “Party’s over. \n”;}
11 $count++;
12 $remain––;
}
print “\n”;
print ’_’ x 30,“\n\n”;
# Initialization, test, and increment, decrement of counters is done in one step.
13 for ($count=1, $beers=10, $remain=$beers; $count <= $beers; $count++,
$remain––){
14 if($remain == 1){print “$remain bottle of beer $where $where ” ;}
15 else{ print “$remain bottles $where $where”;}
16 print “ Take one down and pass it all around.\n”;
17 print “Now ”, $beers – $count , “ bottles of beer $where!\n”;
18 if ( $count == 10 ){print “Party’s over.\n”;}
}
• The foreach loops over each element in the parenthesized list, ARRAY,
assigning each element of the array to a variable, VARIABLE. If VARI-
ABLE is absent, $_ is used.
• The VARIABLE is local to the foreach block. It will regain its former
value when the loop is exited.
• If ARRAY is an array, the array elements can be modified within the loop.
Format:
foreach VARIABLE ( ARRAY ) { BLOCK }
Example 3.25
(In Script)
#!/usr/bin/perl
#Script: foreach_loop_ex1
1 foreach $pal ( ’Tom’, ’Dick’, ’Harry’, ’Pete’ ) {
2 print ”Hi $pal\n”;
}
(The Output)
2 Hi Tom
HI Dick
Hi Harry
HI Pete
Example 3.26
(In Script)
#!/usr/bin/perl
# Script: foreach_loop_ex2
1 foreach $hour ( 0 .. 23 ){
2 print “Good–morning.\n” if $hour > 0 && $hour < 12;
3 print “Happy Lunch.\n” if $hour == 12;
4 print “Good afternoon.\n” if $hour > 12 && $hour <= 17;
5 print “Good–night.\n” if $hour > 17 && $hour < 24;
}
next
next LABEL
last
last LABEL
redo
redo LABEL
• The next statement restarts the next iteration of the loop, skipping over the
rest of the statements in the loop and evaluating the loop expression, like a
C or Csh continue statement.
• The last statement leaves a block and is like the break statement in C and
Csh.
• The redo statement restarts the block without evaluating the loop expres-
sion again.
• The continue block is executed just before the conditional expression is
about to be evaluated again.
Format:
LABEL: while ( EXPR ){ BLOCK}
LABEL: while ( EXPR ) { BLOCK} continue{ BLOCK}
LABEL: until ( EXPR ) { BLOCK} { BLOCK}
LABEL: for ( EXPR; EXPR; EXPR ){ BLOCK}
LABEL: foreach VAR ( ARRAY ){ BLOCK}
LABEL: { BLOCK} continue { BLOCK }
Example 3.27
#!/usr/bin/perl
# Script: labeled_block
1 TRY:{
2 print ”Are you a great person? ”;
3 chomp($answer = <STDIN> );
4 redo TRY unless ”$answer” eq "yes";
}
Example 3.28
In the following example the label is optional. It is used most effectively in nested
loops.
( In Script )
#!/usr/bin/perl
#Script: labels_and_loops
1 ATTEMPT: while (1){ # ATTEMPT is a loop label
Exercise 3A
Operator, operator
1. Print the average of three floating point numbers with a precision of two
decimal places.
$x = $x + 1;
$y = $y + 5;
3. Calculate the volume of a room that is 12.5 ft long and 9.8 ft wide and
10.5 ft high.
C = ( F – 32 ) / 1.8
Randomly print a saying each time the user runs your script. Hint: The
index value of the array will be randomly generated to produce the saying.
Exercise 3B
What Are Your Conditions?
A. Temperature Conversion Script
b. Check for bad input: a temperature less than absolute zero and an ending
temperature that is less than the beginning temperature. The program will
send an error message to STDERR if either condition is detected.
Module 4
Regular Expressions
4.1 Pattern Matching
• A regular expression is a pattern of characters that is used when searching
for a specified pattern of characters in a line of text. The regular expression
can be a word or part of a word and can contain metacharacters.
• Regular expressions in Perl are simply patterns of characters. The pattern
is enclosed in forward slashes.
• The metacharacters are special characters embedded in regular expres-
sions that allow you to control the way a search performed.
Modifiers are:
if EXPR
unless EXPR
while EXPR
until EXPR
foreach EXPR
Example 4.1
In this example, the special filehandle, DATA, is used to read input lines. The
actual data is stored under the special literal __DATA__. This is handy if you
don’t want to open an external file to do simple testing.
(In Script)
while (<DATA>){
print;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
Example 4.2
Print the line if it contains Norma
while (<DATA>){
print if /Norma/;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
4 Norma Cord
Example 4.3
The Modifier must be placed at the end of a statement!
while (<DATA>){
if /Norma/ print; # could be: if (/Norma/){ print; }
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
syntax error in file /tmp/perl–ea01985 at line 1, next 2 tokens ”if /Norma/”
Execution of /tmp/perl–ea01985 aborted due to compilation errors
Example 4.4
Print the line unless it contains Norma
while (<DATA>){
print unless /Norma/;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
5 Jon DeLoach
6 Karen Evich
1 m/Good morning/
2 /Good morning/
3 m#Good morning#
4 /good MORning/i
1 s/old/new/
2 s/old/new/i
3 s/old/new/g
4 s+old+new+g
5 s/old/expression to be executed/e
Example 4.5
Substitute Igor with Boris. Print all lines.
while(<DATA>){
s/Igor/Boris/;
print; # Prints all lines
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
1 Steve Blenheim
2 Betty Boop
3 Boris Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
Example 4.6
Print the line only if Igor is replaced with Boris.
while(<DATA>){
print if s/Igor/Boris/;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
3 Boris Chevsky
Example 4.7
The i modifier turns off case sensitivity. Replace Igor with Boris ignoring the
case in the search pattern; i.e. Igor, IGOR, IGor, etc.
while(<DATA>){
print if s/igoR/Boris/i;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
3 Boris Chevsky
Example 4.8
Replace the first ’e’ on each line with an ’X’.
while(<DATA>){
print if s/e/X/;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
1 StXve Blenheim
2 BXtty Boop
3 Igor ChXvsky
5 Jon DXLoach
6 KarXn Evich
Example 4.9
Replace every occurrence of ’e’ on the line with an ’X’.
while(<DATA>){
print if s/e/X/g;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
1 StXvX BlXnhXim
2 BXtty Boop
3 Igor ChXvsky
5 Jon DXLoach
6 KarXn Evich
Example 4.10
Globally substitute every ’e’ or ’E’ for ’X’ (turn off the case sensitivity)
while(<DATA>){
print if s/e/X/gi;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
1 StXvX BlXnhXim
2 BXtty Boop
3 Igor ChXvsky
5 Jon DXLoach
6 KarXn Xvich
Example 4.11
Substitute the search string with the replacement string after the expression
( 6 * 5 + 4 ) has been evaluated.
while(<DATA>){
print if s/6/6 * 5 + 4/e; # Evaluate the expression
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
34 Karen Evich
Example 4.12
Globally substitute the search string with the replacement string after the ex-
pression ( "*" x 3 ) has been evaluated ( turn off case sensitivity).
while(<DATA>){
print if s/e/"*" x 3/eig; # Globally, evaluate, turn off case
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
1 St***v*** Bl***nh***im
2 B***tty Boop
3 Igor Ch***vsky
5 Jon D***Loach
6 Kar***n ***vich
Example 4.13
(In Script)
1 while(<>){
2 print if /^Igor/;
}
#The $_ variable holds the current line and is matched if it begins with the pat-
tern Igor
Example 4.14
(In Script)
1 while(<>){
2 ($name, $phone, $address) = split(":", $_);
3 print if $phone =~ /^397/;
}
# $phone is matched if it begins with the pattern 397.
Example 4.15
(The Script)
1 #!/usr/bin/perl
2 # pattern matching script perl.pat
3 $name=“Tommy Tuttle”;
4 print $name=~/Tom/, ”\n”; #prints 1 if true
5 print $name=~/Joe/, ”\n”; #print null if false
6 $name=~s/T/M/; print $name,”\n”; #substitute first ‘T’ with an ‘M’
7 $name=”Tommy Tuttle”;
8 $name=~s/T/M/g; print $name,”\n”; #substitute all ‘T’s’ with ‘M’s’
9 $message=“merry christmas”;
10$message=~tr/a–z/A–Z/; # translate all lower case letters to uppercase
11print “$message\n”;
(The Output)
4 1
5
6 Mommy Tuttle
8 Mommy Muttle
11 MERRY CHRISTMAS
Metacharacter Function
. Matches any character except newline
[a–z0–9] Matches any single character in set
[^a–z0–9] Matches any single character not in set
\d Matches one digit
\D Matches a non–digit, same [^0–9]
\w Matches an alpha–numeric ( word ) character
\W Matches a non–alpha–numeric ( non–word ) character
\s Matches white space character
\S Matches non–white space character
\n Matches a newline
\r Matches a return
\t Matches a tab
\f Matches a formfeed
\b Matches a backspace(when inside [ ])
\0 Matches a null character
\12 Matches that octal value
\x811 Matches that hex value
\cX Matches that control character
\[ Matches that metacharacter
(string) Used for backreferencing ( see example )
\1 or $1 Matches first set of parens
\2 0r $2 Matches second set of parens
\3 or $3 Matches third set of parens
x? Matches 0 or 1 x
x* Matches 0 or more x’s
x+ Matches 1 or more x’s
x{m,n} Matches at least m, x’s and no more than n x’s.
abc Matches all of a, b, and c respectively
Examples:
4.7.1 Anchors
Example 4.16
Print lines starting with the number 5.
while(<DATA>){
print if /^5/ ;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
5 Jon DeLoach
Example 4.17
Print lines ending with "ch".
while(<DATA>){
print if /ch$/ ;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
5 Jon DeLoach
6 Karen Evich
Example 4.18
Print “Found Norma” if the “word” Norma is found.
while(<DATA>){
print "Found Norma!\n" if /\bNorma\b/;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
Found Norma!
Example 4.19
Find all lines containing a space, followed by three characters, and another
space.
while(<DATA>){
print if / ... /;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
5 Jon DeLoach
Example 4.20
Substitute the first character with an ’X’, no matter what character it is.
while(<DATA>){
print if s/./X/;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
X Steve Blenheim
X Betty Boop
X Igor Chevsky
X Norma Cord
X Jon DeLoach
X Karen Evich
Example 4.21
Substitute “N", followed by any two characters, followed by "ma”, with
“Jane”. Print all lines.
while(<DATA>){
s/N..ma/Jane/;
print;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Jane Cord
5 Jon DeLoach
6 Karen Evich
while(<DATA>){
print if /[ABC]/;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
Example 4.23
Print lines containing a character in the set, ranging from E to M.
while(<DATA>){
print if /[E-M]/;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
3 Igor Chevsky
5 Jon DeLoach
6 Karen Evich
Example 4.24
Print lines beginning with one of the numbers not in the set 2, 3, or 4.
while(<DATA>){
print if /^[^2-4]/;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
1 Steve Blenheim
5 Jon DeLoach
6 Karen Evich
Example 4.25
Print lines beginning with a single digit, followed by a space (or tab), followed
by three alphanumeric word characters and a space..
while(<DATA>){
print if /^\d\s\w\w\w\s/;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
5 Jon DeLoach
4.11 Quantifiers ( * + ? )
Example 4.26
Print lines matching a B followed by zero or more lowercase letters.
while(<DATA>){
print if /B[a-z]*/; # Zero or more letters between ’a’ and ’z’
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
7 B B King # Added this line for example
(Output)
1 Steve Blenheim
2 Betty Boop
7 B B King
Example 4.27
Print lines matching a B followed by one or more lowercase letters.
while(<DATA>){
print if /B[a-z]+/; # One or more letters between ’a’ and ’z’
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
7B B King # Added this line for example
(Output)
1 Steve Blenheim
2 Betty Boop
Example 4.28
Print lines matching an ’e’ followed zero or one spaces and an upper case
letter.
while(<DATA>){
print if /e\s?[A-Z]/;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
1 Steve Blenheim
5 Jon DeLoach
4.12 Alternation
Example 4.29
Print lines that match Steve, Betty, or Jon
while(<DATA>){
print if /Steve|Betty|Jon/; # Alternation: this, that, and the other thing
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
Output:
1 Steve Blenheim
2 Betty Boop
5Jon DeLoach
4.13 Grouping
Example 4.30
Print lines that match one or more occurrences of ’ma’.
while(<DATA>){
print if /(ma)+/i;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
7Mama Bear # Line added for this example
(Output)
4 Norma Cord
7 Mama Bear
Example 4.31
Print lines that match Steve Blenheim or Alexander Blenheim
while(<DATA>){
print if /(Steve|Alexander) Blenheim/;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
Output:
1 Steve Blenheim
7 Alexander Blenheim
while(<DATA>){
/\s(\w+)\s(\w+)/;
print "$1 $2\n";
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
Steve Blenheim
Betty Boop
Igor Chevsky
Norma Cord
Jon DeLoach
Karen Evich
Example 4.33
Find “Jon” or “jon”, capture the pattern found, store it in $1, and use it in the
replacement string to produce “Jonathan ” or “jonathan.
while(<DATA>){
s/([Jj]on)/$1athan/;
print;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jonathan DeLoach
6 Karen Evich
Example 4.34
Reverse “Steve” and “Blenheim”
while(<DATA>){
print if s/(Steve) (Blenheim)/$2, $1/;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
(Output)
1 Blenheim, Steve
Example 4.35
Reverse first and last names
while(<DATA>){
s/([A–Z][a–z]+)\s([A–Z][a–z]+)/$2, $1/;
print;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
1 Blenheim, Steve
2 Boop, Betty
3 Chevsky, Igor
4 Cord, Norma
5 De, JonLoach # Whoops!
6 Evich, Karen
while(<DATA>){
print if /^\d\s\w{5}\s/;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
1 Steve Blenheim
2 Betty Boop
4 Norma Cord
6 Karen Evich
Example 4.37
Print lines containing at least 15 characters
while(<DATA>){
print if /.{15,}/;
}
__DATA__
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
(Output)
1 Steve Blenheim
Exercise 4A
Regular Expressions––They’re Back...
(Sample file)
Tommy Savage:408–724–0140:1222 Oxbow Court, Sunnyvale,CA 94087:5/19/66:34200
Lesle Kerstin:408–456–1234:4 Harvard Square, Boston, MA 02133:4/22/62:52600
JonDeLoach:408–253–3122:123 Park St., San Jose, CA 94086:7/25/53:85100
Ephram Hardy:293–259–5395:235 Carlton Lane, Joliet, IL 73858:8/12/20:56700
Betty Boop:245–836–8357:635 Cutesy Lane, Hollywood, CA 91464:6/23/23:14500
Wiliam Kopf:846–836–2837:6937 Ware Road, Milton, PA 93756:9/21/46:43500
Norma Corder:397–857–2735:74 Pine Street, Dearborn, MI 23874:3/28/45:245700
James Ikeda:834–938–8376:23445 Aster Ave., Allentown, NJ 83745:12/1/38:45000
Lori Gortz:327–832–5728:3465 Mirlo Street, Peabody, MA 34756:10/2/65:35200
Barbara Kerz:385–573–8326:832 Ponce Drive, Gary, IN 83756:12/15/46:268500
11. Print the file with the first and last names reversed.
Exercise 4B
IS IT SED, AWK, OR GREP?
GIVE PERL A WHIRL!
4. Print lines 2 through 6. ( The $. variable holds the current line number. )
5. Print names and phone numbers of those in the 408 area code.
9. Print the file with a row of stars after the last line.
12. Print all cities in California, and the first names of those people who live there.
13. Without using the split function, print all the lines up to the first colon (Just the names)
14.Without using the split function, print the street address; e.g. 123 Park St.
15. Create and display a new format for all the phone numbers to look like this:
(408) 465-1234
Module 5
Getting a Handle on Files
5.1 User–Defined Filehandles
• A filehandle is a name for a file, device, pipe or socket.
• The open function allows you to create your own filehandle
• The $_ scalar variable is used as the default pattern space for
searches.
It is also used to hold the current line.
• A filehandle remains opened until explicitly closed or the program ends.
• The die function prints a concatenated LIST to STDERR and exits with
the current value of $!, the system error message that you would normally
get if a system call failed. If the LIST does not end in a newline, the die func-
tion prints the LIST and the line where the program died.
Example 5.1
(In a Script)
# The chdir function will try to change directories to /usr/bin/joker
1 chdir "/usr/bin/joker" || die "Can’t cd: $!\n";
# If the call to the system to change directories fails, the die function will
# cause the program to exit with the system message shown in the output.
(The Output)
1 Can’t cd: No such file or directory
• The module Carp.pm (Perl5) was added to refine the way a program dies.
perldoc -f die
• Perl reads from the file when the filehandle is enclosed in angle brack-
ets, called the diamond operators.
Format:
open ( Filehandle, "Unix filename" );
open ( Filehandle, "<Unix filename" );
Example 5.2
(Script)
#!/usr/bin/perl
# open_for_reading_format
1 open (MYHANDLE, “myfile” );
2 while($line=<MYHANDLE>){ # Assign each line of input to $line
3 print $line;
}
4 close(MYHANDLE);
----------------------------------------------------------------
1 open (MYHANDLE, “myfile” );
2 while(<MYHANDLE>){ # Each line is assigned to $_, the default
3 print;
}
4 close(MYHANDLE);
Format:
close ( Filehandle );
Example 5.3
(The file to be opened)
1 Steve Blenheim
2 Betty Boop
3 Igor Chevsky
4 Norma Cord
5 Jon DeLoach
6 Karen Evich
---------------------------------------------------------
( In Script )
#!/usr/bin/perl
# Script: open_for_reading_example
( The Output )
Format:
Example 5.4
( The Script )
#!/usr/bin/perl
# Script: open_for_writing
5 $file=“newfile”;
6 open(HANDOUT, “> $file”) || die “Can’t open $file: $!\n”;
7 print HANDOUT “hello world.\n”; # Output is sent to HANDOUT
8 print HANDOUT “hello world again.\n”;
9 close(HANDOUT);
( The Output )
$ cat newfile # After running the script, display the output file, newfile
7 hello world.
8 hello world again.
Format:
open ( MYHANDLE, “>> myfile”);
Example 5.5
#!/usr/bin/perl
# Script: open_for_appending
1 open(HANDOUT, “>> newfile”) or die print “Can’t open newfile: $!\n”;
2 print HANDOUT “Just appended to \“hello world\” in newfile.\n”;
• The eof function can be used to test if end of file has been reached.
• It returns 1 if either the next read on a FILEHANDLE is EOF or if the file
is not opened.
• Without an argument the eof file returns the eof status of the last file read.
• The eof function can be used in a while loop to test each file in the argu-
ment list, if it is used without parenthesis or the ARGV handle is used in
parenthesis.
Format:
eof(FILEHANDLE)
eof()
eof
Find pattern and print until the end of file is reached. (See range operator.)
Example 5.6
(In Script)
#!/usr/bin/perl
# Script: eof_function1
1 while(<>){
2 print if /pattern/ .. eof;
3 }
Print each line of the file and when end of file is reached, print a row of 30 dashes.
#!/usr/bin/perl
# Script: eof_function2
4 while(<>){
5 print;
6 if (eof) { print “–” x 30, ”\n”;}
}
• The seek function is the same as the fseek standard i/o function in C.
Rather than closing the file, and then reopening it, the seek function allows
you to move to some position within the file.
• Seek allows you to randomly access a file.
• The tell function returns the current byte position in the file and is used
with the seek function to move to that position in the file.
Format:
• Seek sets a position in a file, where the first byte is 0. Positions are:
• The offset is the number of bytes from the file position. A positive offset
moves the position forward in the file; a negative offset moves the position
backward in the file for position 1 or 2.
Example 5.7
(The Script)
1 #!/usr/bin/perl
# Script: seek_function
2 open(PASSWD,”/etc/passwd”) || die ”Can’t open: $!\n”;
3 while($line=<PASSWD>){ # loop through the whole file
4 if ($line =~ /daemon/) { print ”––$line––\n”;}
}
6 seek(PASSWD,0,0); # Seek to the beginning of the file
7 while(<PASSWD>) { # Read from the beginning of the file
8 print if /root/;
}
Format:
tell(FILEHANDLE)
tell
Example 5.8
(The Script)
#! /usr/bin/perl
# Script: tell_function
Example 5.9
(Check the permissions on perl.test)
1 $ ls –l perl.test
–rwxr–xr–x 1 ellie 417 Apr 23 13:40 perl.test
2 $ ls –l afile
–rws––x––x 1 ellie 0 Apr 23 14:07 afile
(In Script)
#!/usr/bin/perl
# Script: file_testing_ex1
$file=perl.test;
(The Output)
1 File is readable
2 File is writeable
3 File is executable
4 File is a regular file
5 *** No print out here because the file is not a directory ***
6 File is text file
7 File was last modified 0.000035 days ago.
8 File has read, write, and execute set.
10File is a set user id program.
11 File is zero size.
12xxyyzz: No such file or directory
Example 5.10
(The Script)
#! /usr/bin/perl
#Script: file_testing_ex2
#
1 open(FIND,”find . –name ’perl*’ –print |”) || die ”UNIX find command failed: $!\n”;
2 while($filename=<FIND>) {
3 chomp $filename ; # get rid of that trailing newline. Important!
4 if ( –r $filename && –w _ && –x _) {
5 print ”$filename is readable, writeable, and executable.\n”; }
6 if ( –T $filename) {
print ”$filename is a text file.\n”;
}
}
––––––––––––––––––––––––––––––––––––––––––––––
If the –T or –B switches are used first block of the file is examined for weird char-
acters. If over 30% of the characters are weird, such as control characters, then
the file is a –B (block special file); otherwise the file is a –T ( file text file).
• Unlike C and awk, ARGV[0] does not represent the name of the pro-
gram; it represents the name of the first word after the script name.
• Like the shell languages, the $0 special variable is used to hold the name
of the Perl script.
• The $#ARGV variable contains the number of the last subscript in the
array, not the number of elements in the array.
assigned to ARGV and the @ARGV array is shifted immediately to the left
by one, thereby shortening the @ARGV array. The value that is shifted off
the @ARGV array is assigned to $ARGV.
Example 5.11
(The Script)
$!/usr/bin/perl
1 die "$0 requires an argument.
3 print "$ARGV[0]
4 print "$ARGV[1]
(Output)
$ perl.arg
2 perl.arg requires an argument.
$ perl.arg f1 f2 f3 f4 f5
2 f1 f2 f3 f4 f5
3 f1
4 f2
5 There are 5 arguments.
6 f5 is the last one.
• Perl shifts through the array, storing each element of the array in a variable
$ARGV. A set of empty angle brackets is called the null filehandle and Perl
implicitly uses each element of the ARGV array as a filehandle.
• When using the input operators <>, either with or without the keyword
ARGV, Perl shifts
Example 5.12
(The Text Files)
$ cat f1
Hello there. Nice day.
$ cat f2
Are you sure about that?
$ cat f3
This is it.
This is the end.
(The Script)
1 while( <ARGV> ) {print ;}
2 print "The value of \$ARGV[0] is $ARGV[0].
(Output)
$ argv.test f1 f2 f3
Hello there. Nice day.
Are you sure about that?
This is it.
This is the end.
The value of $ARGV[0] is .
Example 5.13
(The Text File: emp.names)
Steve Blenheim
Betty Boop
Igor Chevsky
Norma Cord
Jon DeLoach
Karen Evich
(The Script)
# Scriptname: grab.pl
# Program will behave like grep -- will search for a pattern
# in any number of files.
Example 5.14
1 if ( ($#ARGV < 1 ) {die "Usage: $0 pattern filename(s)
2 $pattern = shift;
3 while($line=<ARGV>){
print "$ARGV: $.: $line" if $line =~ /$pattern/i;
close(ARGV) if eof;
}
(Output)
$ grab.pl
1 Usage: grab.pl pattern filenames(s)
$ grab.pl 'norma' db
2 db:5: Norma Cord
$ grab.pl Steve d*
5 datebook.master:12: Johann Erickson:Stevensville, Montana
datafile:8: Steven Daniels:496-456-5676:83755:11/12/56:20300
db:1: Steve Blenheim
Example 5.15
(The Script)
1 unless ( $#ARGV == 0 ){ die "Usage: $0 <argument>: $!"; }
2 open(PASSWD, "etc/passwd") || die "Can't open: $!";
3 $username=shift(@ARGV);
4 while( $pwline = <PASSWD>){
5 unless ( $pwline =~ /$username:/){ die "$username is not
a user here.
}
6 close PASSWD;
7 open(LOGGEDON, "who |" ) || die "Can't open: $!" ;
8 while($logged = <LOGGEDON> ){
Exercise 5
Getting A Handle on Things
5A
1. Create a filehandle for reading from the ”datebook” file; print to another
filehandle the names of all those who have a salary greater than $50,000.
2. Ask the user to input data for a new entry in the ”datebook” file. (The
name, phone, address, etc., will be stored in separate scalars.) Append the
new line to the ”datebook” file by using a user–defined filehandle.
5B
1. In the ”datebook” file create a number of duplicate entries. Fred Fard-
barkle, for example, might appear five times, and Igor Chevsky three times,
etc. If you’re using the vi editor, just ”yank” and ”put” some of the entries.
Write a program that will assign the name of the ”datebook” file to a scalar
and check to see if the file exists. If it does exist, the program will check to
see if the file is readable and writeable. Use the die function to send any
errors to the screen. Also tell the user when the ”datebook” was last modi-
fied.
The program will read each line of the ”datebook” file giving each person a
10% raise in salary. If, however, the person appears more than once in the
file, (assume having the same first and last name means it is a duplicate) he
will be given a raise the first time, but if he appears again, he will be skipped
over. Send each line of output to a file called ”raise”. The ”raise” file should
not contain any person’s name more than once. It will also reflect the 10%
increase in pay.
Display on the screen the average salary for all the people in the ”datebook”
file. For duplicate entries, print the names of those who appeared in the file
more than once and how many times each appeared.
Module 6
Modularizing Perl
(Subroutines, Packages, Libraries)
6.1 Subroutines
• A subroutine statement is not executable, so can be anywhere in the script.
• Subroutine definitions are preceded by the keyword sub and the name of
the subroutine.
• Subroutines are invoked by prefixing the subroutine name with an amper-
sand, &. In Perl5, the ampersand is not necessary if the subroutine has a for-
ward reference or its name is followed by parentheses. A forward reference
is normally placed near the top of the program and consists of the keyword
sub and the name of the subroutine.
• Variables used in subroutines are global by default.
• Arguments, whether scalar values or arrays are passed call by reference.
• The @_ is a special array that handles arguments passed to the subroutine.
The @_ array is local to the subroutine. It’s values refer to the actual scalar
parameters. These values can be modified.
• Call by reference is achieved with a method called typeglob (aliasing).
• The local or my functions are used to turn on call–by–value and are highly
recommended by the Perl authors. The my function was introduced in Perl5
to ensure that variables are local only to the subroutine in which they are
created.
• The return value is the value of the last expression evaluated (either scalar
or array ). The return function can be used, but is not necessary, and a
bit slower.
• If the call to the subroutine is made part of an expression, the returned
value can be assigned to a variable, thus emulating a function call.
• To check if a subroutine exists, the defined function can be used.
Format:
Subroutine definition:
subroutine_name { statement; statement; }
Subroutine call:
&subroutine_name;
&subroutine_name(parameter1, parameter2, ... )
Example 6.1
(The Script)
Script: perlsub
#!/usr/bin/perl
# Script: perl_sub2
1 # Variables used in subroutines are global by default.
3 $name=“Ellie”;
4 print “Hello to you and yours!\n”;
5 &bye ; # Call subroutine
6 print “Out of the subroutine. Hello $name.\n" # $name is now Tom
(The Output)
4 Hello to you and yours!
2 Bye Ellie
6 Out of the subroutine. Hello Tom.
Forward Reference
• A forward reference announces to the compiler that the subroutine has
been defined somewhere in the program.
• The ampersand is not needed to call a subroutine if it has been forward ref-
erenced.
Example 6.2
#!/usr/bin/perl
1 sub bye; # Forward reference
$name="Ellie";
2 print "Hello $name.\n";
4 sub bye{
5 print "Bye $name\n";
}
(Output)
2 Hello Ellie.
5 Bye Ellie
Example 6.3
#!/usr/bin/perl
1 $name="Ellie";
2 print "Hello $name.\n";
6.2 Arguments
6.2.1 Passing by Reference
Example 6.4
The following example demonstrates:
1. How to pass arguments.
2. How to reference arguments in a subroutine with the @_ array.
(The Script )
#!/usr/bin/perl
# Script: perl_sub2
1 $first=“Steve”;
2 $last=“Blenheim”;
3 while(<>){
4 &greeting ( $first, $last ) if /[Ss]teve/;
5 }
6 sub greeting{
7 print “Welcome to the club, $_[0] $_[1]\n”;
8 print "@_";
}
(The Output)
$ perl_sub2 emp.names
7 Welcome to the club, Steve Blenheim
8 Steve Blenheim
Example 6.5
(The Script)
#!/usr/bin/perl
4 sub guests{
my $friend = "Pat";
my $pal = "Chris";
print "In the guests subroutine:
5 $friend and $pal are welcome guests!\n\n";
}
6 &guests;
(The Output)
3 Louise and Danny are global in scope.
Example 6.6
#!/usr/bin/perl
# Default package is main
# Scriptname: strict_perl
(The Output)
2 Global symbol "town" requires explicit package name at strict_perl line 2.
5 Global symbol "town" requires explicit package name at strict_perl line 5.
Execution of package3 aborted due to compilation errors.
Example 6.7
(The Script )
#!/usr/bin/perl
# Script: perl_sub4
1 $first=Tom;
2 $last=Jones;
3 &greeting ( $first, $last ) ;
4 print “–––$fname–––\n”;
# Won’t print a value; $fname is local to the greeting function
5 sub greeting{
6 my ($fname, $lname) = @_ ; # $fname and $lname are local
7 print ”Welcome $fname!!\n”;
}
( The Output )
7 Welcome Tom!!
––––––
Example 6.8
(The Script)
#!/usr/bin/perl
# Script: return_statement
1 sub MAX {
2 my($max) = shift(@_);
3 foreach $foo ( @_ ){
4 $max = $foo if $max < $foo;
5 print $max,”\n”;
6 }
7 print ”–––––––––––––––––––––––––––––\n”;
8 return $max;
}
9 sub MIN {
10 my($min) = pop( @_ );
11 foreach $foo ( @_ ) {
12 $min = $foo if $min > $foo;
13 print $min,”\n”;
14 }
15 print ”–––––––––––––––––––––––––––––\n”;
16 $min;
}
(The Output)
3
4
10
100
100
–––––––––––––––––––––––––––––
20
2
2
2
2
–––––––––––––––––––––––––––––
The biggest is 100 and the smallest is 2.
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
6.4 Packages
• Packages are used to create privacy. Variables in one package are not
known in another package (although they can be known).
• By default the main part of your program is called package “main”.
• All variables are global in the main package
• The package allows you to switch namespaces, so that variables in the
package are private, even if they have the same name somewhere outside
the package. A package contains symbols just as a directory contains files.
• The scope of the package is from from the declaration of the package to
the ending curly brace of the block following the declaration. Normally the
package is declared right before a subroutine or group of subroutine defini-
tions and there is one package per file.
• To reference a package (Perl5) variable in another package, the package
name is followed by two colons and the variable name, e.g.,
$package::variable.
Note that the dollar sign to indicate a scalar type variable precedes
the name of the package, not the variable name,
When referring to the main package, the name of the package can
be eliminated.
• Perl4 used an apostrophe to separate the package name from the variable,
e.g,.
$package’variable
y %x (HASH)
&x (SUB)
z
Example 6.9
(The Script)
#!/bin/perl
# Package main
1 $name="Tom";
2 @name=qw(Joe Jeff Jan );
7 package friends;
8 print "Hello $main::dude, dude.\n";
9 print "My pal is $main::pal.\n";
(The Output)
4FileHandle:::*main::FileHandle
@: *main::@
name: *main::name
stdin: *main::stdin
STDIN: *main::STDIN
": *main::"
stdout: *main::stdout
STDOUT: *main::STDOUT
$: *main::$
_<perlmain.c: *main::_<perlmain.c
key: *main::key
ENV: *main::ENV
_<package.dump: *main::_<package.dump
/: *main::/
ARGV: *main::ARGV
0: *main::0
STDERR: *main::STDERR
stderr: *main::stderr
: *main::
DynaLoader::: *main::DynaLoader
: *main::
main::: *main::main
DATA: *main::DATA
DB::: *main::DB
INC: *main::INC
value: *main::value
_: *main::_
-------------------------
12 Hello Ernie, dude.
13My pal is .
Example 6.10
The following example demonstrates
1. The declaration of a package
2. The scope of package variables,
3. How to reference variables in other packages using both Perl5 and Perl4.
(The Script)
#!/usr/bin/perl
# Script: package_example
1 $name=“Suzanne”; # defined in package mai
2 $num=100;
3 sub welcome {
4 package friend;
5 print “Who is your pal? ”;
6 chomp($name=<STDIN>);
7 print “Welcome $name!\n”;
8 print ”Where is $main::name?\n”;
9 print ”\$num is $num.\n”; # $num unknown in this package
10} # Package friend scope ends here
11 &welcome;
12print “Out of the subroutine. \$name is $name\n”;
13print “Bye ”,$friend::name,“\n”; # switch namespace to friend package
14print “Bye $name\n”; # Back in main package
15package birthday;
16$name="Beatrice";
( The Output )
5 Who is your pal? Tommy
7 Welcome Tommy!
8 Where is Suzanne?
9 $num is .
12 Out of subroutine, $name is Suzanne
13 Bye Tommy
14 Bye Suzanne
Example 6.11
(The Script)
#!/usr/bin/perl
# Default package is main
1 use strict ’vars’; # Makes sure that global or local variables are outlawed
Example 6.12
(The Script)
#!/usr/bin/perl
1 # Default package is main
2 # Scriptname: strict_perl
3 use strict ;
4 @town = ( "Boston", "Chico", "Tampa" ); # Now didn’t I tell you?
5 my $friend="Mary";
(The Output)
4 Global symbol "town" requires explicit package name at strict_perl line 4.
7 Global symbol "town" requires explicit package name at strict_perl line 14.
Execution of package3 aborted due to compilation errors.
------------------------------------------------------------------------
Example 6.13
#!/usr/bin/perl
package Presents;
use strict;
1 use vars qw( @toys ); # Old way, before "our"
@toys = qw( doll train legos puppet );
2 our @stores = qw( KMart Sears Wallmart ); # Perl 5.6+
$toys[0] = "Barbie\n";
print "@toys\n";
sion, .pm. The package used as a module has the same name as the .pm file.
For example, Addit.pm is the file and Addit is the package name, now called
module Addit.
• The use function imports modules into your program. The files that con-
tain the module normally end in .pm. The .pm suffix is not needed with use.
The no function lets you undefine a particular module used in your program.
The use function is handled at compile time.
Format:
require(”file.pl”);
require ”file.pl”;
require 5.6.1;1
require Socket.pm
require Socket; # also loads a .pm file
use Module;
no Module;
Note: To see the directories where your Perl libraries are distributed, type at
the command line:
Example 6.14
(The Script) Script: midterms
1 % cat midterms
2 #!/usr/bin/perl
3 unshift(@INC, ”./mylibs”);
4 require ”average.pl”;
5 print ”Enter your midterm scores.\n”;
1. If using 5.002 or any lower version than 5.003, complains "Perl 5.003 required--this is only version 5.002..."
6 @scores=split(’ ’, <STDIN>);
7 printf ”The average is %.1f.\n”, $average=&ave(@scores);
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
8 % cd mylibs # Directory where library is located
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
• The use function allows the correct importation of Perl modules and prag-
mas into your program at compile time.
• The use function will not import a module if the module’s filename does
not have the .pm extension.
• The module is loaded with use at compile time, whereas with require it is
loaded at run time. Normally the @INC array is updated at run time. To
make sure that it is updated for the use function you can try any one of the
following:
Examples:
(In .login) setenv PERL5LIB "directory path"
(In .profile) PERL5LIB "directory path"; export PERL5LIB
(In perl script) BEGIN{ unshift(@INC, "directory path");}
(In perl script) use lib ("directory path");
Format:
use Module;
use Module(list);
use Directory::Module;
use pragma(list);
no pragma;
Example 6.15
1 package Carp;
# This package implements handy routines for modules that wish to throw
# exceptions outside of the current package.
2 @ISA = Exporter;
3 require Exporter;
4 @EXPORT = qw(confess croak carp);
5 sub longmess {
my $error = shift;
my $mess = ””;
my $i = 2;
my ($pack,$file,$line,$sub);
while (($pack,$file,$line,$sub) = caller($i++)) {
$mess .= ”\t$sub ” if $error eq ”called”;
$mess .= ”$error at $file line $line\n”;
$error = ”called”;
}
$mess || $error;
}
6 sub shortmess {
my $error = shift;
my ($curpack) = caller(1);
my $i = 2;
my ($pack,$file,$line,$sub);
while (($pack,$file,$line,$sub) = caller($i++)) {
return ”$error at $file line $line\n” if $pack ne $curpack;
}
longmess $error;
}
If you create a subroutine by the same name as one of the library routines,
listed as arguments to Carp, your subroutine will take precedence. If you try
to call one of the subroutines from Carp.pm that are not listed for import,
you will get an error message. In order, in the following example, to call
confess or carp from Carp.pm, their names must be fully qualified,
Carp::confess or Carp::carp.
Example 6.16
#!/bin/perl
1use Carp qw(croak); # Import the croak function. If you want to use either
# confess or croak, must fully qualify the name; e.g. Carp::confess.
2print "Give me a grade: ";
$grade = <STDIN>;
3try($grade); # Call subroutine
4sub try{
5 my ($number)=@_;
6 croak "Illegal value: " if $number < 0 || $number > 100;
}
(The Output)
2Give me a grade: 200
6Illegal value: at expire line 13
main::try called at expire line 8
2. This new function, called cluck, has been added to the Carp.pm module; in fact, Carp.pm has been re-writ-
ten with embedded documentation. Go to the standard Perl library to see the new look.
Example 6.17
(At The Command Line)
% cat Module/Me.pm
1 package Me;
use strict;
2 require 5.6.0; # Make sure this is Perl5
3 require Exporter; # Exporter.pm allows modules to be imported
4 our @ISA=qw(Exporter); # ISA is a list of packages to import
5 our @EXPORT=qw(hello goodbye ); # list of subroutines to export
6 sub hello { my($name)=shift;
print ”Hi there, $name.\n” };
7 sub goodbye { my($name)=shift;
print ”Good bye $name.\n”;}
8 sub do_nothing { print ”Didn’t print anything. Not in EXPORT list\n”; }
1;
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
% cat main.perl
#!/usr/bin/perl
9 use lib (”/home/ellie/Module”); # Update @INC array at compile time
10use Me; # Import package
11&hello (’Danie’l);
12&goodbye (’Steve’);
13&do_nothing; # This was not on the Export list in Me.pm so cannot be imported
(The Output)
11 Hi there, Daniel.
12 Good–bye Steve.
13 Undefined subroutine &main::do_nothing
Exercise 6
1. Write a program called ”tripper” that will ask the user the number of
miles he has driven and the amount of gas he used. In the tripper script,
write a subroutine called mileage that will calculate and return the user’s
mileage (miles per gallon). The number of miles driven and the amount of
gas used will be passed as arguments. All variables should be my variables.
Print the results.
2. Hotels are often rated by stars where a 5 star hotel may have a king size
bed, a kitchen, and 2 tv's, while a 1 star hotel may have cockroaches and a
leaky roof. Write a subroutine called, "printstar" that will produce a histo-
gram to show the star rating for hotels shown in the following hash. The
"printstar" function will be given two parameters, the name of the hotel and
the number of its star rating. (Hint: sort the hash keys into an array. Use a
loop to iterate through the keys, calling the printstar function for each iter-
ation. )
Hotel Category
------------------------------------------
Best Western |**** |
Days Inn |*** |
Hilton |***** |
Motel 6 |** |
Rancho El Cheapo |* |
Regent |***** |
-----------------------------------------
(Note that the hotel names have been sorted ).
Exercise 6B
1a. Create a module called "Checking.pm"
b. Create a script that will act as the user interface; i.e. a script that will
"use" the Checking.pm module. This script will be called myATM.plx.
It will contain a "here document" that will produce the following menu:
1) Deposit
2) Withdraw
3) Current Balance
4) Exit
Ask the user to select one of the menu items. Until menu item #4 is
selected, the program will go into a loop to re-display the menu and wait for
him to select another transaction. The subroutines will be called by quali-
fying the subroutine name with the name of the Checking package; e.g.
Checking::deposit().
. If the user chooses number 4, when the program exits, print today’s date
and the current balance to a file called "register".
2. Re-write the Checking module so that it gets the balance from the file
"register" if the file exists; otherwise it will start at a zero balance. Each
time the program exits, save the current balance, the time and date in the
"register" file.
3. Can you create more than one account, e.g. an account for three differ-
ent users?
Exercise 6c
1a.Create an EXPORT list in the Checking module which will consist of all
the names that will be imported my the user of the module. (The names will
be the names of the subroutines.)
b. In the myATM.plx file, use the Checking module, and remove the colon
syntax from each of the function calls that are listed in the EXPORT list in
Checking.pm.
c. Move the Checking.pm module into its own library (directory) and reset
the @INC array in the myATM file to include this new libary.
b. Download the "Switch.pm" module from CPAN (Use ppm. If you have
ActiveState. It’s easy) Use this module in your Checking.pm file. After the
user selects an entry from the menu, use the switch mechanism provided by
the Switch.pm module rather than the if/elsif construct to check the user’s
selections.
Module 7
References
7.9 Hard References (Pointers)
• Perl5 references can also be called pointers. If you know C, Perl pointers
will be easy to understand.
• A pointer is a scalar that contains the address of a variable. When a
backslash precedes the funny character that represents the data type of
a variable, the address of that variable is assigned to a scalar.
• A scalar that holds the address can be called a pointer.
• A pointer contains the address of a scalar, array, associative array, or
subroutine e.g, $ref=\$n says that $ref is a pointer to a scalar $n.
$ref=\@n says that $ref is a pointer to the array @n.
• A pointer can be dereferenced, i.e., the value stored at that address can
be fetched by prefixing the pointer variable, a scalar, with the funny symbol
for the variable type it references e.g., @$pointer dereferences an array;
$$pointer dereferences a scalar.
Example 7.18
(The Script)
#!/usr/bin/perl
1 @toys=qw(Barbie Elmo Thomas);
2 $num = @toys; # Get the number of toys
3 %games = ( "Nintendo"=> "Wii",
"Sony"=>"PlayStation 3",
"Microsoft" => "XBox 360");
(The Output)
7 There are 3 toys.
8 They are Barbie Elmo Thomas
9 Willie's favorite toy is Thomas
10Debbie's favorite toy is Barbie
11 Microsoft => XBox 360
Sony => PlayStation 3
Nintendo => Wii
3
SCALAR(0x182efa8ref)
ref1 $num
0x4588
Example 7.19
(The Script)
#!/usr/bin/perl
# Script: anon_arr_hash
1 $arrayref = [ ’Woody’, ’Buzz’, ’Bo’, ’Mr. Potato Head’ ];
2 print $arrayref–>[0], ”\n”; # or $$arrayref[0]
3 print "The number of elements in the array are ", $#{$arrayref} + 1, ".\n";
(The Output)
2 Woody
3 The number of elements in the array are 4.
Example 7.20
(The Script)
#!/usr/bin/perl
1 $hashref = { "Name"=>”Woody”, "Type"=>”Cowboy”};
2 print $hashref–>{"Name"}, ”\n\n”; # or $$hashref{Name}
3 print keys (%$hashref);
print ”\n”;
(The Output)
2 Woody
3 NameType
Example 7.21
(The Script)
# Scriptname: anon_toys
1 $hashref = { "ToyName" => "Lego",
2 "Shape" => [ "Square", "Triangle", "Rectangle" ],
3 "Color" => [ "Red", "Green", "Blue", "Yellow" ],
};
# Shape and Color are keys. The associated values are anonymous lists.
4 print "The toy is a $hashref->{ToyName}, it is a $hashref->{Shape}->[0]
shape, and its color is $hashref->{Color}->[2].\n";
(The Output)
4 The toy is a Lego, it is a Square shape, and its color is Blue.
Example 7.22
(The Script)
1 $ptr = { "Teacher"=>{"Subjects"=>[ qw(Science Math PE) ]},
"Musician"=>{"Instruments"=>[ qw(piano flute harp)]},
};
# Teacher and Musician are keys. The values consist of nested hashes.
2 print $ptr->{"Teacher"}->{"Subjects"}->[0],"\n";
3 print "@{$ptr->{Musician}->{Instruments}}\n";
(Output)
2 Science
3 piano flute harp
Example 7.23
(The Script)
1 $subref = sub { print @_ ; };
2 $subref->(’a’,’b’,’c’); #call the subroutine
print ”\n”;
(The Output)
1 abc
Example 7.24
(The Script)
#!/usr/bin/perl
# Two dimensional array
1 $matrix = [ [ 0, 2, 4],
[ 4, 1, 32 ],
[ 12, 15, 17 ]];
2 print "Row 3 column 2 is $matrix->[2]->[1].\n";
3 for($x=0;$x<3;$x++){
for($y=0;$y<3;$y++){
4 print "$matrix->[$x]->[$y] ";
}
print "\n";
}
(The Output)
2 Row 3 column 2 is 15.
4 024
4 4 1 32
4 12 15 17
Example 7.25
(The Script)
#!/usr/bin/perl
1 sub gifts;
2 $num = 3;
3 @toys = qw( Buzzlightyear Woody Thomas );
4 gifts( \$num, \@toys ); # passing by reference
5 sub gifts {
6 my( $n, $t) = @_; # localizing the reference with my
7 print ”There are $$n gifts: ”;
8 print ”@$t\n”;
}
(The Output)
7 There are 3 gifts: Buzzlightyear Woody Thomas
Example 7.26
(The Script)
#!/usr/bin/perl
1 sub gifts; # forward reference
2 $num = 3;
3 $junk = ”xxx”;
4 @toys = qw( Buzzlightyear Woody Thomas );
5 gifts( \$num, \@toys, $junk ); # $junk is not a reference
6 sub gifts {
7 my( $n, $t, $j) = @_;
8 print ”\$n is a reference.\n” if ref($n);
9 print ”\$t is a reference.\n” if ref($t);
10 print ”\$j is a reference.\n” if ref($j); # not a reference; nothing prints
11 printf”\$t is a reference to an %s.\n”, ref($t);
}
(The Output)
8 $n is a reference.
9 $t is a reference.
11 $t is a reference to an ARRAY.
perldoc Data::Dumber
NAME
Data::Dumper - stringified perl data structures, suitable for both
printing and "eval"
SYNOPSIS
use Data::Dumper;
# configuration variables
{
local $Data::Dumper::Purity = 1;
eval Data::Dumper->Dump([$foo, $bar], [qw(foo *ary)]);
}
# OO usage
$d = Data::Dumper->new([$foo, $bar], [qw(foo *ary)]);
...
print $d->Dump;
...
$d->Purity(1)->Terse(1)->Deepcopy(1);
eval $d->Dump;
Example 4.27
1 use Data::Dumper;
2 my $petref = [
3 { name=>"Rover",
type=>"dog",
owner=>"Mr. Jones",
},
{ name=>"Sylvester",
type=>"cat",
owner=>"Mrs. Black",
},
{ name=>"Tweetie",
type=>"bird",
owner=>"Ms. Singer",
},
];
3 $Data::Dumper::Indent=1;
4 print Dumper($petref);
(Output)
$VAR1 = [
{
'owner' => 'Mr. Jones',
'name' => 'Rover',
'type' => 'dog'
},
{
'owner' => 'Mrs. Black',
'name' => 'Sylvester',
'type' => 'cat'
},
{
'owner' => 'Ms. Singer',
'name' => 'Tweetie',
'type' => 'bird'
}
];
Example 7.28
1 use Data::Dumper;
2 open(DB, "datebook") or die "Can't open file: $!\n";
3
4 # Create an array of hashes, and a reference to the array
5
6 while (<DB>) {
7 ($h{name},$h{phone},$h{address},$h{birthday},$h{salary}) = split(":",$_);
8 push(@aofh,{%h}) unless $_ =~ /^ *$/; # Create an array of hashes
9 }
10
11 foreach $record (@aofh){
12 foreach $field (values %$record){
13 print "$field\n";
14 }
15 }
16
17 print Dumper(\@aofh);
(Sample output)
Steve Blenheim
95 Latham Lane, Easton, PA 83755
238-923-7366
11/12/56
20300
Betty Boop
635 Cutesy Lane, Hollywood, CA 91464
245-836-8357
6/23/23
14500
Igor Chevsky
3567 Populus Place, Caldwell, NJ 23875
385-375-8395
6/18/68
23400
--------------------Data Dumper Output----------------
$VAR1 = [
{
'name' => 'Steve Blenheim',
'address' => '95 Latham Lane, Easton, PA 83755',
'phone' => '238-923-7366',
Exercise 7
What’s the Point?
1. Create two arrays: the first one an array of numbers
10 floating point numbers, and the second array containing
numbers integers between between 1 and 150.
Send the addresses of these arrays to a function called ave()
that will return the average of all the numbers. Print with
average with a precision of one decimal place.
2. Rewrite the last exercise so that the hash is anonymous and assign the
anonymous hash to a reference. Delete one of the keys from the hash using
the reference ( use the delete function).
Module 8
Perl Objects
8.1 Object Oriented Perl
• Object oriented languages, such as C++ and Java, bundle up data into a
variable and call it an object. The object’s data describes the properties, also
called attributes. The object’s data is normally kept private. Messages are
sent to the object through special subroutines called methods. These sub-
routines provide "methods" to get at the data. The methods are normally
public. The only way that a user of the program should access the data is
through these methods.
• The data and the methods are packaged up into a data structure called a
class. A Perl package will function as a class when using the object oriented
approach. The object oriented approach is often compared to real life situa-
tions. For example, you are a member of the mammal class, Queen Eliza-
beth is in a high social class, and a Ford Explorer is in a class of cars called
sports vehicles.
• The published interface is the written documentation describing how the
programmer should use a class (e.g. what arguments will be passed to a
method ). The interface should not change, even if something in the class is
changed.
• In Perl modules are special packages (in a .pm file) that are defined in a
library. A module may also function as a class.
• Perl does not use keywords such as private, public, or protected.
• A Perl class is a package that combines data and subroutines. The subrou-
tines are called methods. These methods are used to manipulate the data in
the class, e.g., they allow the data to be retrieved, displayed, updated, etc.
• When functioning as a class, double colons (scope operator) are not
required when calling a method from another package.
• The data is normally stored in an anonymous hash. The address of the
anonymous hash is assigned to a reference. The reference is made private
to the class with the my function.The bless function makes sure that an
object belongs to a specific class by tagging the object with an internal
pointer.
• An object and all access to the object are managed by methods. 1
• A module can export its symbols (variables and subroutines) to other pro-
grams with the Exporter module. A module can list the symbols it is willing
to export in two special arrays, @EXPORT and @EXPORT_OK.
• When used as a class, a module doesn’t need to explicitly export its sym-
bols. Perl handles all the details of exportation and importation.
• Inheritance is when a new class is derived from an existing (base) class.
This is accomplished in Perl by putting the "base" class names in the special
@ISA array.
• Modules can provide both a procedural interface and an object oriented
interface; that is, the module can contain exported subroutines as well as
objects and methods.
1. Unlike most object-oriented languages, Perl does not enforce encapsulation of data; i.e. you can directly
access the object’s data, even though it is against all the cardinal rules of oop to do so.
8.3 Classes
• A Perl class is a package containing variables to represent the data and
special subroutines called methods to act on the data.
• A class normally consists of:
1. The data (also called properties or attributes) that belongs in the
class.
2. Subroutines that know how to access and manipulate the data in
the class.
• Because it is a package, a class has its own symbol table.
• To keep variables private, the my function is used. The my variables exist
only within the innermost enclosing block, subroutine, eval or file. The my
variables cannot be accessed from another package by using the double
colon or single apostrophe.
Package A Package B
$x $x
8.4 Objects
• An object in Perl is created with a hard reference (pointer).
• An object and its attributes are described in a package; when the object is
created it takes up a region in memory; it is instantiated.
• A reference is normally assigned the address of an anonymous hash. The
hash will contain the data members of the object (similar to a C struct).
sub new{
Attributes/data Constructor method
Bless the object
} (Create the object)
sub setdata{ }
Access methods
( store and fetch
data from the object)
sub getdata{ }
• The bless function blesses the object being referenced2 into the pack-
age, not the reference itself.
Format:
bless REFERENCE, CLASSNAME;
bless REFERENCE;
return REFERENCE;
Example:
$reference = {};
bless( $reference, $class);
return $reference;
or
return bless($reference, $class);
Example 8.1
(The Script)
1 package Employee; # Package declaration
(The Output)
4 The bless function tags the hash with its package name.
5 The value of \$ref is: Employee=HASH(Ox5a08a8).
6 The ref function returns the package name: Employee.
7 The employee’s name is Tom.
8.5 Methods
• A method is a subroutine that operates on an object.
• It is a special subroutine that belongs to a class and expects its first argu-
ment to be a package name or a reference to an object. Otherwise, it looks
like any other subroutine.
• A method is used primarily to assign or change the data in an object or to
retrieve data from an object.
• There are two types of methods:
A Class
Data to access
private data
The first example for each method is called the indirect syntax; the sec-
ond example, using the arrow operator, is called the object oriented syntax.
When Perl sees one of the above methods being invoked, it knows what
class the object belongs to because the object was blessed ( an internal
pointer is tracking where it is).3
If you call either:
display $ref ($args);
or
$ref->display($args);
and $ref points to an object in a package (class) called "Employee":
Perl translates that to:
Employee::display($ref, $args);
3. The ability of Perl to call the approprate module’s function is called run-time binding. (Advance Perl Pro-
gramming , O’Reilly & Associates, 1997, ISBN: 1-56592-220-4).
package ClassExample;
sub new{
my $class=shift; Constructor method
my $ref = {};
bless ( $ref, $class); (Create the object)
return $ref;
}
sub setdata {
my $self=shift; Access methods
$self->{key}=value; ( store and fetch
} data from the object)
sub getdata {
my $self = shift;
print $self->{key};
}
1;
Example 8.2
(The Module: Employee.pm)
1 package Employee; # class
(The Output)
11 $empref in main belongs to class Employee.
12 Name is Dan Savage.
13 Salary is 75000.
Example 8.3
(The Module: Employee.pm)
1 package Employee;
2 sub new{ # Class/Static method
3 my $class = shift;
4 my $worker={}; # Anonymous and empty hash
5 bless($worker, $class);
6 return $worker;
}
7 sub set_name{ # Instance method used to access object’s data
8 my $self = shift;
9 print "\$self is a class ", ref($self)," reference.\n";
10 $self->{Name} = shift;
}
11 sub get_name { # Instance method
12 my $self = shift; # The object reference is the first argument
13 print "The worker is ", $self->{Name},"\n";
}1;
------------------------------------------------------------------------------------------------------------
(The User Script)
#!/usr/bin/perl
14 use Employee;
15 my $emp = Employee->new(); # Call class method and create the object
16 $emp->set_name("Tom Savage"); # Object oriented syntax The object
# set_name $emp("Tom Savage"); # Call instance method after the blessing
17 $emp->get_name; # Object oriented syntax Employee
is tagged with its
class, Employee.
# get_name $emp; # Call instance method
0x5a08a8
(The Output)
0x5a08a8 $empref points to the object
9 $self is a class Employee reference.
13 The worker is Tom Savage $empref
Example 8.4
(The Module:Employee.pm)
#!/bin/perl
1 package Employee;
2 sub new{ # Constructor method
3 my $class = shift;
4 my ($name, $salary) = @_; # Instance variables
5 my $worker={’Name’=>$name,
’Salary’=>$salary,
# Instance variables to initialize the object
};
6 bless($worker, $class);
7 return $worker;
}
8 sub display { # An instance method
9 my $self = shift; # The name of the object is passed
10 while( ($key, $value)=each %$self
){ print "$key: $value \n";}
}
1;
---------------------------------------------------------------------------------------------
#!/usr/bin/perl
11 use Employee;
# Documentation explaining how to use the employee package is called the
# public interface. It tells the programmer how to use the class.
# To create an Employee object requires two arguments, a name and salary.
# Invoking constructor--two ways
# my $emp1 = new Employee("Tom Savage", 250000);
12 my $emp1 = Employee->new("Tom Savage", 250000);
13 my $emp2 = Employee->new("Devin Quigley", 55000);
# Two objects have been created.
# Invoking the methods--two ways
(The Output)
15 Name: Tom Savage
Salary: 250000
16 Name: Devin Quigley
Salary: 55000
17 Employee=HASH(0x9d450), Employee=HASH(0xa454c)
Example 8.5
# Program to demonstrate passing arguments to an instance method.
# When the method is called the user can select what he wants returned.
1 package Employee;
2 sub new{ # Constructor
my $class = shift;
my ($name, $salary, $extension) = @_; #Instance variables
my $worker = {_Name=>$name,
_Salary=>$salary,
_Extension=>$extension,
};
return bless($worker,$class);
}
3 sub display { # Instance method
4 my $self = shift; # Object reference is the first argument
5 foreach $choice ( @__){
6 print "$choice: $self->{$choice}\n";
}
}
-------------------------------------------------------------------------------------------------
#!/usr/bin/perl
7 use Employee;
8 $emp = Employee-> new("Tom Savage", 250000, 5433);
9 $emp->display ("_Name", "_Extension"); # Passing arguments to instance
# method
(Output)
6 _Name: Tom Savage
6 _Extension: 5433
Example 8.6
(The Module: Employee.pm)
1 package Employee;
sub new{
my $class = shift;
$worker={_Name=>undef,
_Salary=>undef,
};
2 bless($worker, $class);
return $worker; }
3 sub DESTROY{ # Getting control of an object before it is destroyed
my $self = shift;
4 print "Hash Name entry still exists.\n" if exists $self->{_Name};
5 delete $self->{_Name};
6 print "Hash entry was destroyed. Bailing out...\n"
if ! exists $self->{_Name};
}
------------------------------------------------------------------------------------
(The User Script)
#!/bin/perl
7 use Employee;
8 my $empref = Employee->new(); # Create the object
9 $empref->{_Name}="Dan Savage";
$empref->{_Salary}=10000;
10 print "Name is $empref->{_Name}.\n";
11 print "Salary is $empref->{_Salary}.\n";
(Output)
10 Name is Dan Savage.
11 Salary is 10000.
4 Hash Name entry still exists.
6 Hash entry was destroyed. Bailing out...
8.7 Inheritance
• Inheritance means that a new class can inherit methods from an existing
class. The new class can then add to or modify existing code to customize
the class without having to reinvent what has been done before.
• The principle is that a class may be subdivided into a number of subclasses
that all share common features, but each subclass may provide its own addi-
tional features by refining what it borrows to a more specific functionality.
• In object oriented programming, once a class has been written and
debugged, it can be stored in a library and reused by other programmers. A
programmer can then add features and capabilities to the existing class with-
out rewriting the whole thing. This is done through inheritance, that is, by
deriving a new class from an existing class.
• The derived class can override methods in the base class.
• If an AUTOLOAD function isn’t found, Perl searches for the last time in a
special predefined package called UNIVERSAL. The UNIVERSAL class is a
global base class for all packages, the highest class in the hierarchy of
classes.
• The @ISA array is not searched in a call to a normal subroutine, but in a
call to a subroutine if it is called with the method invocation syntax.
Example 8.7
(The Script)
#!/bin/perl
# Example of attempting inheritance without updating the @ISA array.
1 { package Grandpa;
2 $name = "Gramps";
3 sub greetme {
print "Hi $Child::name I'm your $name from package Grandpa.\n";
}
}
4 { package Parent;
# This package is empty.
}
5 {package Child;
6 $name = "Baby";
7 print "Hi I'm $name in the Child Package here.\n";
8 Parent->greetme(); # Use method invocation syntax
}
(The Output)
7 Hi I'm Baby in the Child Package here.
8 Can't locate object method "greetme" via package "Parent" at inher.file line 23.
Example 8.8
(The Script)
#!/bin/perl
# Example of attempting inheritance by updating the @ISA array.
1 { package Grandpa;
$name = "Gramps";
sub greetme {
2 print "Hi $Child::name I'm your $name from package Grandpa.\n";
}
}
3 { package Parent;
4 @ISA=qw(Grandpa); # Grandpa is a package in the @ISA array.
# This package is empty.
}
5 {package Child;
$name = "Baby";
6 print "Hi I'm $name in the Child Package here.\n";
7 Parent->greetme(); # Parent::greetme() will fail. No such function in Parent
}
(The Output)
6 Hi I'm Baby in the Child Package here.
2 Hi Baby I'm your Gramps from package Grandpa.
Example 8.9
# Module Employee.pm
1 package Employee; # Base Class
use strict;
use warnings;
# Constructor method
2 sub new {
my $class = shift;
my $self = {_Name=>undef,
_Address=>undef,
_BasePay=>undef,
};
3 return bless($self, $class);
}
# Instance/access methods
4 sub set_data{
my $self=shift;
print "Enter the name of the employee. ";
chomp($self->{_Name}=<STDIN>);
print "Enter the address of $self->{_Name}. ";
chomp($self->{_Address}=<STDIN>);
print "Enter the monthly base pay for $self->{_Name}. ";
chomp($self->{_BasePay}=<STDIN>);
}
5 sub get_data{
my $self=shift;
my ($key,$value);
print "Name = $self->{_Name}.\n";
while(($key,$value)=each(%$self)){
$key =~ s/_//;
print "$key = $value.\n" unless $key eq "Name";
}
print "\n";
}
1;
Example 8.10
# Module Salesman.pm
1 package Salesman;
use strict;
use warnings;
2 BEGIN{unshift(@INC, "./Baseclass");};
3 our @ISA=qw( Employee);
4 use Employee;
# What does the saleman inherit from the employee?
12 sub set_data{
my $self=shift;
13 my $calc_ptr = sub{ my($base, $comm, $bonus)=@_;
return $base+$comm+$bonus; };
print "Enter $self->{_Name}'s commission for this month. ";
chomp($self->{_Commission}=<STDIN>);
print "Enter $self->{_Name}'s bonuses for this month. ";
chomp($self->{_Bonuses}=<STDIN>);
print "Enter $self->{_Name}'s sales region. ";
chomp($self->{_Region}=<STDIN>);
14 $self->{_PayCheck}=&$calc_ptr( $self->{_BasePay},
$self->{_Commission},
$self->{_Bonuses}
);
}
1;
Example 8.11
#!/usr/bin/perl
# User creates two saleman objects
1 use Salesman;
use strict;
use warnings;
2 my $salesguy1=Salesman->new();
3 my $salesguy2=Salesman->new();
4 $salesguy1->set_data;
5 $salesguy2->set_data;
6 $salesguy1->get_data; # Inheritance!
7 $salesguy2->get_data;
Example 8.12
(Here is the documentation found at the end of the BigFloat.pm module in the standard Perl
library, under the subdirectory Math)
=head1 NAME
=head1 SYNOPSIS
use Math::BogFloat;
$f = Math::BigFloat->new($string);
=head1 DESCRIPTION
All basic math operations are overloaded if you declare your big
floats as
=over 2
=back
=head1 BUGS
=head1 AUTHOR
Mark Biggar
=cut
Explanation
The preceding text is what is called a "pod" file. It consists of lines starting with an
equal sign and text, followed by a blank line. Perl provides a special translator pro-
gram that reads the pod file and translates it into a readable file, either in plain text,
HTML format, nroff text, or Latex. The next section describes how to use the pod
filter programs to make the translation for you.
See http://perldoc.perl.org/perlpod.html
• It’s easy to embed pod instructions in a text file. Commands are placed
at the beginning of a line, starting with =pod (or any other pod command)
and ending with =cut. Everything after the first =pod instruction to the
=cut instruction will be ignored by the compiler, just as comments are
ignored. The nice thing about using the commands is that they allow you to
create bold, italic, plain text, to indent, to create headings, etc. The chart
below contains a list of instructions.
• To achieve line breaks, precede each line of text that will be printed with a space.
If the interpreter is not in your search path, you can copy the one you want into
your own directory: e.g.
$ cp /usr/bin/perl5/bin/pod2text .
You may also copy the library routine into your directory; e.g.
$ cp /usr/bin/perl5/lib/BigFloat.pm .
Now when you list the contents of the directory, you should have both the
pod interpreter and the library module.
$ ls
BigFloat.pm
pod2text
To translate the pod commands, give the library module to the pod inter-
preter and create an output file to save the translated text. If you don’t redi-
rect the output to a file, it will simply go to the screen.
$ cat BigFloat.Text (The output file after pod commands have been
translated into text.)
NAME
Math::BigFloat - Arbitrary length float math package
SYNOPSIS
use Math::BogFloat;
$f = Math::BigFloat->new($string);
DESCRIPTION
All basic math operations are overloaded if you declare your big
floats as
$float=newMath::BigFloat"2.123123123123123123123123123123123";
number format
canonical strings have the form /[+-]\d+E[+-]\d+/ . Input
values can have inbedded whitespace.
Division is computed to
`max($div_scale,length(dividend)+length(divisor))' digits by
default. Also used for default sqrt scale.
BUGS
The current version of this module is a preliminary version of
AUTHOR
Mark Biggar
Example 8.13
#!/bin/perl
1 use Math::BigFloat; # BigFloat.pm is in the Math directory
2 $number = "000.95671234e-21";
3 $mathref = new Math::BigFloat("$number"); # Create the object
# Return value of NaN means the string is not a number or you divided by zero, or
you took the square root of a negative number.
Output
$mathref is in class Math::BigFloat
+95671234E-29
The sum of .00000000000000000000095671234 + 500 is:
+50000000000000000000000095671234E-29
Division using overloaded operator:
.000000000000000000000004771632618453865336658354114713216957606
Division using fdiv method:+4771632618453865336658354114713216957606E-
63
Enter a number hello
You didn't enter a number.
Exercise 8
Part 1 Intro to Objects
d. In another Perl script, use the Rightnow module to create a Rightnow object,
and call the "print_time" method to produce output as follows:
a. In a class, create a student object. The attributes for the student object
will be sent as arguments to the constructor method. The student
object will have 3 attributes: the name of the student, the student's
Major, and a list of courses he is taking.
The user of the module will create two student objects and display
each one.
Id: 123A
StartDate: 01/10/04
Tuition: 5400.55
How will you manage this? If the user has so much information to
pass to the constructor, it may be a good time to create an access
method called "set_student".
The user interface will allow the user to add or drop any number
of courses by sending a list of parameters to the methods;
e.g. $ptr->add_courses(["C++", "Java"]);
2. You will use a "class" method to keep track of the number of new
students. Each time you add a student, update the counter. Before
exiting the program, print the number of new students. Use the
DESTROY method.
3. From now on, send the data for each student to a file.
It should contain a line that looks like this:
John Doe:14 Main St:3456IX:Math:Trigonometry,Calculus,
French:01/01/06:4500
a. Make Checking.pm object oriented. The object will be "the balance" and the
subroutines will be "methods". The constructor will contain at least two attributes:
the balance, account number. The account number will be passed to the construc-
tor as an argument. The balance will be retrieved from the register, initially set to 0.
When you create the register file, append the account number to the file name.
Include the account number, balance, and date in the register file.
Use the Checking module in the ATM user script you created earlier.
b. Can you make more that one instance of the checking object and keep track of
the balance for each account?
owner
name
sex
b. Create two classes that will inherit from the Pet class; for example,
a Dog and a Cat class. They will use the Pet's constructor and
add new attributes of their own. They will have a speak() method
but not an eat() method.
8.10.1 The steps for retrieving the Expect.pm Module from CPAN:
cpan> help
Display Information
command argument description
a,b,d,m WORD or /REGEXP/ about authors, bundles, distributions, modules
i WORD or /REGEXP/ about anything of above
r NONE reinstall recommendations
ls AUTHOR about files in the author's directory
# cd /usr/y/build
# ls
DBI-1.55 Expect-1.21 IO-Tty-1.07
# cd IO*
# ls
# perl Makefile.PL
# make
And then:
# make install
Documentation:
perldoc Expect
NAME
Expect.pm - Expect for Perl
VERSION
1.21
SYNOPSIS
use Expect;
$exp->send("string\n");
USAGE
new Expect ()
Creates a new Expect object, i.e. a pty. You can change parameters
on it before actually spawning a command. This is important if you
want to modify the terminal settings for the slave. See slave()
below. The object returned is actually a reblessed IO::Pty file-
handle, so see there for additional methods.
Expect->exp_init(\*FILEHANDLE) or
Expect->init(\*FILEHANDLE)
Initializes $new_handle_object for use with other Expect functions.
It must be passed a _reference_ to FILEHANDLE if you want it to
work properly. IO::File objects are preferable. Returns a refer-
ence to the newly created object.
You can use only real filehandles, certain tied filehandles (e.g.
Net::SSH2) that lack a fileno() will not work. Net::Telnet objects
can be used but have been reported to work only for certain hosts.
YMMV.
Expect->spawn($command, @parameters) or
$object->spawn($command, @parameters) or
new Expect ($command, @parameters)
Forks and execs $command. Returns an Expect object upon success or
"undef" if the fork was unsuccessful or the command could not be
found. spawn() passes its parameters unchanged to Perls exec(), so
look there for detailed semantics.
Note that if spawn cannot exec() the given command, the Expect
object is still valid and the next expect() will see "Cannot exec",
so you can use that for error handling.
Also note that you cannot reuse an object with an already spawned
command, even if that command has exited. Sorry, but you have to
allocate a new object...
Example 8.14
1 #!/usr/bin/perl -w -s
2 # $Id: get_file,v 1.1 2001/04/08 20:39:12 jsh Exp $
3 use File::Basename;
4 our $debug;
5 use Expect;
10 my $t = 30;
11 my $ftp_prompt = 'ftp> ';
12 if ($debug) {
13 $Expect::Debug=1;
14 $Expect::Exp_Internal=1;
15 }
41 $ftp->hard_close();
Physical Setup
N M
Generate user.params
and check topology;
initiate log file.
log files
Example 8.15
#!/volume/perl/bin/perl
# Template: S03.02.P09.T05
# Copyright (C) 2003-2004, Juniper Networks, Inc.
# All rights reserved.
#
# Author: Phil Wisdom
# %SYN%: Tests forwarding on OC192 or something.
# %URL%: None yet, sucka!
# %REV%: Script revision is tracked by $VERSION found below.
# %DESCR%: For fun configuring of traffic meshes on OC192 links for RLI
2741 and others.
#
#-----------------------------------------------------------------------
use warnings;
use strict;
use vars qw($VERSION);
use JT::Test;
use Forwarding; # See Forwarding.pm
main: {
my $t = JT::Test->init;
$t->setup;
$t->run_testcases;
$t->close;
}
This is a large file. The following example represents sections, but not all
of the file.
Example 8.16
# template: S03.02.P09.T05
# Copyright (C) 2003-2004, Juniper Networks, Inc.
# All rights reserved.
#
# This Perl module is used by 'Forwarding testcases'.
#
# Author: Vinay Kulkarni
# Acknowledgement: Phil Wisdom
# Description: The purpose of this .pm is a library to quickly configure
# and reconfigure traffic meshes for OC192 links.
1 package Forwarding;
2 use warnings;
3 use strict;
4 use Exporter; # Exporting symbols to user’s symbol table
5 use JT;
use JT::Test;
use JT::Scaling;
use RT_Scaling;
use SP_Config;
9 sub setup {
10 my $t = shift; # Test object
11 my $sub = JT::sub_name;
12 my ($p, @r, $v, $rt);
13 $t->get_handles(params=>\$p, rtrs=>\@r, vars=>\$v, rt=>\$rt);
## call object method
$t->checkpoint(msg=>"Configuring RT and R0");
my $status = $t->ok;
#######################
# setup trend_data file
#######################
### Call a function to create the trend_data file and assign its name as a
### value to an anonymous hash referenced by pointer $v:
### the key to the hash:dfh (data file handle)
14 $v->{dfh} = JT::create_file( ext => "trend_data", headline => 1 );
## $v is a pointer to a hash. Function create_file reutrns value (file name)
## assigned to hash where key is ’dfh’
15 my $date = `date "+DATE: %Y-%m-%d %H:%M:%S"`; # Unix/Linux
chomp $date;
my $junos = $r[0]->get_version();
### Print to the file referenced by $v the current date and version info
print {$v->{dfh} } "$date $0 $junos DUT $v->{R0_NAME}
$v->{R0_MODEL}\n";
##############################################################
### Forwarding.pm continues from the last example. We are still in the
### setup() routine
###############
# configure DUT (Juniper Router)
###############
1 my $r0_interfaces = $p->access("r0.interfaces");
2 foreach (keys %$r0_interfaces) {
3 my $pic = $p->access("r0.interfaces.$_.pic");
4 if ($pic =~ /so/) {
### Call the config_build function. Pass a hash to set the interface to
### configure the juniper router
5 $r[0]->config_build(cmd=>["set interface $pic encapsulation ppp"]);
6 $r[0]->config_build(cmd=>["set interface $pic sonet-options fcs 32"]);
}
11 if ($v->{ENABLE_BGP}) {
$r[0]->config_build("set routing-options autonomous-system
$v->{AS}");
}
12 $r[0]->commit;
##################################################
###############
# configure RT0 Still in the setup() routine.
###############
13 my $i = 0;
14 my $rt_interfaces = $p->access("rt0.interfaces");
15 my @port_to_ip;
=pod
my $speed="";
my $rt_port = $p->access("rt0.interfaces.$_.pic");
my $rt_ip = $p->access("rt0.interfaces.$_.x-ip");
17 if ( $v->{SET_CARD_TYPE} ) {
$type = $v->{CARD_TYPE};
$speed = "10G";
}
### An array of ports attributes being set
18 $port_to_ip[$i] = {port=>$rt_port, ip=>$rt_ip, type=>$type,
speed=>$speed};
$i++;
}
20 if ($v->{ENABLE_BGP}) {
21 my $i = 1;
foreach (keys %$rt_interfaces) {
my $rt_port = $p->access("rt0.interfaces.$_.pic");
my $port_handle = $rt->{PORT_TO_HANDLE_MAP}->{$rt_port};
my $x_ip = $p->access("rt0.interfaces.$_.x-ip");
my ($rtr1,$tester1) = get_first_and_last(net=>$x_ip);
22 $rt->close () unless ($rt->add_rt_bgp_to_links(
port_handle=>$port_handle,
num_peers=>1,
num_routes=>$v->{MAX_ROUTES},
type=>"internal",
route_ip=>"$i.0.0.0",
sut_ip=>$rtr1,
tester_ip=>$tester1,
tester_as=>$v->{AS})
);
$i++;
} # End foreach loop
} # End if
23 configure_traffic($t);
24 configure_traffic_statistics($t);
26 return $status;
} # End the setup() routine
1 sub test {
2 my $t = shift; # Test object
my $sub = JT::sub_name;
3 my ($p, @r, $v, $rt); $t->get_handles(params=>\$p, rtrs=>\@r,
vars=>\$v, rt=>\$rt);
my $testname = "REFERENCE"; # can be "REFERENCE", "FIREWALL"
my $status = $t->ok;
4 my $rt_interfaces = $p->access("rt0.interfaces");
my $jcells;
########
5 my $r0_interfaces = $p->access("r0.interfaces");
my $fpc;
6 foreach (keys %$r0_interfaces) {
my $pic = $p->access("r0.interfaces.$_.pic");
$jcells = (($pic =~ /so/) ? 71 : 25);
$fpc = $r[0]->get_pfe(if=>$pic);
}
########
7 if ($v->{ENABLE_BGP}) {
$rt->start_routing;
$status &= $r[0]->chk_bgp_peer(num=>$v->{TOTAL_BGP_PEERS},
timeout=>$v->{BGP_PEER_TIMEOUT});
my $bgp_target = $v->{TOTAL_BGP_PEERS} * $v->{MAX_ROUTES};
$status &= monitor_route_summary(rtr=>$r[0], protocol=>'BGP',
target=>$bgp_target, timeout=>$v->{BGP_ROUTES_TIMEOUT});
}
# my @packetsizes = @{$v->{PACKETSIZES}};
# my $packetsize;
8 my @packetsizes;
9 my $packetsize;
10 if ($v->{PACKET_SWEEP}) {
11 for(my $i=40; $i<108; $i++) {
15 $t->sleep(10);
################################################################
##############################
# Get the snapshot before test, but after all the configs are committed.
# This will give us an idea about the occupied resources!
################################################################
##############################
################################################################
##############################
# Continue with the actual test with traffic flow
################################################################
##############################
my $load_time = time;
$r[0]->load_config_file(
local_file=>$v->{FW_CONF_FILE},
option=>'merge',
timeout=>3600,
keep=>'yes',
synchronize=>'false',
);
$load_time = (time - $load_time);
$t->log(msg=>"X-FILTER-LOAD-TIME $load_time");
my @commit_time = $r[0]->commit(timeout=>3600,synchronize=>'false');
$t->log("X-FILTER-COMMIT-TIME for DUT is $commit_time[1]");
#################################
# Install it on the interfaces
#################################
my $k = 0;
my $r0_interfaces = $p->access("r0.interfaces");
foreach (keys %$r0_interfaces) {
my $pic = $p->access("r0.interfaces.$_.pic");
if ($v->{FULL_MESH}) {
} else {
if ($k < $v->{NUM_SRC_PORTS}) {
$k++;
} else {
$r[0]->config_build(cmd=>["set interface $pic unit 0 family inet filter
output test_filter"]);
$k++;
}
}
}
my @commit_time = $r[0]->commit(timeout=>3600,synchronize=>'false');
$t->log("X-FILTER-COMMIT-TIME for DUT is $commit_time[1]");
$t->sleep(30);
################################################################
# Make sure the filter has been installed
################################################################
#
my $start_time = time;
my $wait_count = 1;
while (1) {
$r[0]->cli(cmd=>"show firewall | match test_filter | count", timeout=>600);
my $filter_count = $r[0]->get_response();
$filter_count =~ s/\D+//g;
$t->log(msg=>"filter count is $filter_count");
last if ($filter_count == 1);
return $t->nok("pfe never got all the filters?") if ($wait_count > 100);
$t->sleep(10);
$wait_count++;
}
###############################
# break down traffic by DS bits
###############################
$rt->invoke("AgtStatisticsList ListHandles");
my $response = $rt->get_response;
my $junk;
($junk, $response) = split /{/, $response;
($response, $junk) = split /}/, $response;
my @stat_handles = split / /, $response;
foreach (@stat_handles) {
my $number;
my $total=0;
my $i=0;
foreach $number (@stat_numbers) {
$t->log("STAT ELEMENTS: $stat_numbers[$i] $number\n");
$total += $number;
$i++;
foreach $number (@stat_numbers) { $total += $number; }
my $DS_bit_percent;
if ($throughput->[5] > 0) {
$DS_bit_percent = ($total / $throughput->[5]) * 100;
}
if ($stat_name =~ /stats/) {
$rt->invoke("AgtStreamStatistics GetAccumulatedValues $_");
my $stats = $rt->get_response;
($junk, $stats) = split /{/, $stats;
($stats, $junk) = split /}/, $stats;
my @stat_numbers = split / /, $stats;
my ($stream_min, $stream_max, $stream_avg);
my $i = 0; my $number;
($junk, $stats) = split /{/, $stats;
($stats, $junk) = split /}/, $stats;
my $num_streams = @stat_numbers;
$num_streams = $num_streams / 3; #min, max, latency
foreach $number (@stat_numbers) {
if ($i == 0) { $stream_min += $number; }
if ($i == 1) { $stream_max += $number; }
if ($i == 2) { $stream_avg += $number; }
$i++;
if ($i > 2) { $i = 0; }
}
$stream_min = ($stream_min / $num_streams) / 100;
$stream_max = ($stream_max / $num_streams) / 100;
$stream_avg = ($stream_avg / $num_streams) / 100;
}
}
############
# trend data
############
################################################################
##############################
# Get the snapshot after test. This will give us the stats on how the resourc-
es were taxed
################################################################
##############################
########################################
# Move to the next packet size
########################################
$i++;
}
} # End of for loop with $iter
# JT::pause(1);
sub test_fail {
my $t = shift; # Test object
my $sub = JT::sub_name;
my ($p, @r, $v, $rt); $t->get_handles(params=>\$p, rtrs=>\@r, vars=>\$v,
rt=>\$rt);
$t->checkpoint(msg=>"Test failed...");
my $status = $t->nok;
return $status;
}
sub configure_traffic {
my $t = shift; # Test object
my $sub = JT::sub_name;
my ($p, @r, $v, $rt); $t->get_handles(params=>\$p, rtrs=>\@r, vars=>\$v,
rt=>\$rt);
my $rt_interfaces = $p->access("rt0.interfaces");
my $i = 0;
my $bw;
my @stream_vals = @{$v->{DS_STREAM_VALS}};
my @stream_bws = @{$v->{DS_STREAM_BWS}};
my @streams;
$i = 0;
# JT::pause(1);
} else {
my $i=0;
my @hPort;
my @hProfile;
my @hStream;
foreach (keys %$rt_interfaces) {
################################################################
#######
# Configure one Profile per port (if the traffic profile is uniform)
################################################################
#######
# $hPort[$i] = $p->access("rt0.interfaces.$_.pic");
$hPort[$i] = $rt->{PORT_TO_HANDLE_MAP}->{$p->access("rt0.interfac-
es.$_.pic")};
$rt->invoke("AgtProfileList AddProfile $hPort[$i]
AGT_CONSTANT_PROFILE");
$hProfile[$i] = $rt->get_response;
put_log("Profile: $hProfile[$i] on port handle $hPort[$i]");
my $profilename = "AGT_CONSTANT_PROFILE" . $hProfile[$i];
$rt->invoke("AgtProfileList SetName $hProfile[$i] $profilename");
$rt->invoke("AgtConstantProfile SetMode $hProfile[$i]
AGT_TRAFFIC_PROFILE_MODE_CONTINUOUS");
$rt->invoke("AgtConstantProfile SetAverageLoad $hProfile[$i] $v-
>{TRAFFIC_LOAD} $v->{TRAFFIC_UNIT}");
$rt->invoke("AgtConstantProfile Enable $hProfile[$i]");
################################################################
####
# Add traffic stream(s) to each of the profiles created above
################################################################
####
##########################################
=pod
put_log(msg=>" Defining profiles...");
$rt->invoke("AgtProfileList AddProfile $traffic_mesh_ports[0]
AGT_CONSTANT_PROFILE");
my $response = $rt->get_response();
my $hProfile = parse_resp($response);
=pod
$rt->invoke("AgtMeshList ListHandlesByType AGT_IPV4_MESH");
my $meshes = $rt->get_response();
my $bracket;
($bracket, $meshes) = split /{/, $meshes;
($meshes, $bracket) = split /}/, $meshes;
my @mesh_handles = split / /, $meshes;
foreach (@mesh_handles) {
# $rt->invoke("AgtIpv4Mesh GetPdu $_");
$rt->invoke("AgtStreamGroup GetPdu $_");
my $pdu = $rt->get_response;
# $rt->invoke("AgtIpPdu SetPacketLength $pdu $packetsize");
$rt->invoke("AgtStreamGroup SetLengthMode $pdu
AGT_PACKET_LENGTH_MODE_IP_PACKETS");
$rt->invoke("AgtStreamGroup SetLength $pdu
AGT_PACKET_LENGTH_FIXED $packetsize");
# $rt->invoke("AgtIpPdu SetIpFieldValue $pdu AGT_IP_TOS_PRECEDENCE
0x6"); # Set the ToS field
}
=cut
# JT::pause(1);
return $status;
}
x-no-resource-reservation-check 1;
#########################
# JT defaults :
#########################
x-show-log 1;
x-log-listing-on-close 2;
x-no-check-interface-status 1;
x-no-check-interface-ping 1;
x-no-commit-on-cleanup 1;
x-no-config-save-on-setup 1;
x-no-save-base-test-config 1;
x-no-params-expand 0;
x-no-params-expand 0;
#x-params-import "";
x-show-log 1;
x-log-level "trace"; # info | trace
# x-log-dir "";
x-xlog 0; # wow
x-cmd-log-level "trace";
x-resp-log-level "trace";
x-no-log-header 0;
x-show-expect-log 0;
x-set-expect-errors 10;
x-log-listing-on-close 0;
x-no-checkpoint 0;
x-no-os-version-chk 0;
x-no-os-version-chk-on-init 0;
x-no-config-save-on-setup 1;
x-no-save-base-test-config 1;
x-no-base-config-cleanup 1;
x-no-setup-interfaces 0;
x-no-commit-on-cleanup 1;
x-no-commit-on-config-setup 0;
x-sleep-interval-after-test-config 10;
x-no-check-interface-status 1;
x-no-check-interface-ping 1;
x-setup-only 0;
x-test-only 0;
x-no-postmortem 0;
x-postmortem-always 0;
x-no-restore-config 0;
x-parallel-timeout 900;
x-timeout-commit-cleanup 3600;
x-timeout-commit-test-config 3600;
x-timeout-restore-config 100;
x-timeout-restore-base-test-config 3600;
x-set-user-configs"&Forwarding::setup";
x-task-memory-snapshot 0;
x-test-descr " Performance with DCP enabled for default routing table
";
x-test-topology "
RT0_NAME
RT0------R0-------RT0
R0_NAME RT0_NAME
";
##########################
# TRAFFIC KNOBS
##########################
x-my-traffic-unit "AGT_UNITS_MBITS_PER_SEC" ; #
"AGT_UNITS_PERCENTAGE_LINK_BANDWIDTH"; #
AGT_UNITS_MBITS_PER_SEC | AGT_UNITS_PACKETS_PER_SEC
x-my-packet-sweep "1"; # set this to zero if you need customized packetsizes array
as shown below
# if set to 1, the loop inside the program will decide the range of
packetsizes
# 40 through 9000+ bytes
#x-my-packetsizes ("40" "53" "64" "75" "90" "110" "128" "256" "512" "1024");
x-my-packetsizes ("52" "53" "54" );
#x-my-packetsizes ("40" "53" "64" "65" "75" "90" "100" "110" "114" "128" "129"
"140" "150" "160" "178" "192" "193" "200" "210" "225" "242" "256" "257" "265" "275"
"290" "300" "316" "320" "321" "340" "350" "360" "370" "384" "385" "390" "400" "410"
"425" "434" "448" "449" "460" "475" "490" "498" "512" "513" "1024" "2048");
x-my-traffic-duration "60"; # seconds
x-my-color "color-blind"; # "color-aware"
x-my-set-card-type "0"; # set this to zero if you want the default card type
x-my-card-type "10GBASE_R"; # 10GBASE_W | 10GBASE_W_PACKET |
10GBASE_R_PACKET
x-my-card-speed "10G"; # 1000 | OC192 | OC12
##########################
# PROTOCOL KNOBS2
##########################
x-my-as "100";
x-my-enable-bgp "1";
x-my-total-bgp-peers "2";
x-my-bgp-peer-timeout "300";
x-my-bgp-routes-timeout "600";
x-my-bgp-type "internal";
x-my-max-routes "1000";
x-my-bgp-hold-time "600";
##########################
# TESTCASES
##########################
x-testcase-001 (
"x-is-run"1
"x-cmd""&Forwarding::test"
"x-cmd-on-fail""&Forwarding::test_fail"
"x-reset-config"0
);
##########################
# TOPOLOGY
##########################
r0 {
x-dut 1;
system {
name "mohawk";
x-my-as 100;
}
interfaces {
r0rt0-0 {
type "sonet";
x-ip "192.1.1.1/30";
name "so-7/0/0.0";
}
r0rt0-1 {
type "sonet";
x-ip "192.2.1.1/30";
name "so-7/1/0.0";
}
# r0rt0-2 {
# type "sonet";
# x-ip "192.3.1.1/30";
# name "xe-0/2/0.0";
# }
# r0rt0-3 {
# type "sonet";
# x-ip "192.4.1.1/30";
## name "xe-0/3/0.0";
# }
}
}
rt0 {
system {
name "art4-ipv6";
make "Agilent";
model "RT";
}
interfaces {
r0rt0-0 { type "sonet"; x-ip "192.1.1.1/30"; }
r0rt0-1 { type "sonet"; x-ip "192.2.1.1/30"; }
# r0rt0-2 { type "sonet"; x-ip "192.3.1.1/30"; }
# r0rt0-3 { type "sonet"; x-ip "192.4.1.1/30"; }
}
}
===== Display starts at offset 16526751 within file of length 16657823. ====
===== Use File->Reload (Cmd-R) to display more. ====
23 [TRACE] [RT0 tx-art1.1]
Apr 12 11:13:23 [RT:TRACE] [tx-art1] 0 "AGT_STATISTICS_IP405"
Apr 12 11:13:23 [INFO ] [Forwarding.pm:378] stat_name is "AGT_STATISTICS_IP405"
Apr 12 11:13:23 [RT:TRACE] [tx-art1] RT->_invoke: invoke AgtStatisticsList GetName 406
Apr 12 11:13:23 [TRACE] [RT0 tx-art1.1] [cmd] invoke AgtStatisticsList GetName 406
Apr 12 11:13:23 [TRACE] [RT0 tx-art1.1]
Apr 12 11:13:23 [RT:TRACE] [tx-art1] 0 "AGT_STATISTICS_IP406"
Apr 12 11:13:23 [INFO ] [Forwarding.pm:378] stat_name is "AGT_STATISTICS_IP406"
Apr 12 11:13:23 [RT:TRACE] [tx-art1] RT->_invoke: invoke AgtStatisticsList GetName 407
Apr 12 11:13:23 [TRACE] [RT0 tx-art1.1] [cmd] invoke AgtStatisticsList GetName 407
Apr 12 11:13:23 [RT:TRACE] [tx-art1] 0 "AGT_STATISTICS_IP412"
Apr 12 11:13:23 [INFO ] [Forwarding.pm:378] stat_name is "AGT_STATISTICS_IP412"
Apr 12 11:13:23 [RT:TRACE] [tx-art1] RT->_invoke: invoke AgtStatisticsList GetName 413
Apr 12 11:13:24 [RT:TRACE] [tx-art1] 0 "AGT_STATISTICS_IP416"
Apr 12 11:13:24 [INFO ] [Forwarding.pm:378] stat_name is "AGT_STATISTICS_IP416"
Apr 12 11:13:24 [RT:TRACE] [tx-art1] RT->_invoke: invoke AgtStatisticsList GetName 417
Apr 12 11:13:24 [TRACE] [RT0 tx-art1.1] [cmd] invoke AgtStatisticsList GetName 417
Apr 12 11:13:24 [TRACE] [RT0 tx-art1.1]
Apr 12 11:13:24 [RT:TRACE] [tx-art1] 0 "AGT_STATISTICS_IP417"
Apr 12 11:13:24 [INFO ] [Forwarding.pm:378] stat_name is "AGT_STATISTICS_IP417"
Apr 12 11:13:24 [RT:TRACE] [tx-art1] RT->_invoke: invoke AgtStatisticsList GetName 418
Apr 12 11:13:24 [TRACE] [RT0 tx-art1.1] [cmd] invoke AgtStatisticsList GetName 418
Apr 12 11:13:24 [TRACE] [RT0 tx-art1.1]
Apr 12 11:13:24 [RT:TRACE] [tx-art1] 0 "AGT_STATISTICS_IP418"
Apr 12 11:13:24 [INFO ] [Forwarding.pm:378] stat_name is "AGT_STATISTICS_IP418"
Apr 12 11:13:24 [RT:TRACE] [tx-art1] RT->_invoke: invoke AgtStatisticsList GetName 419
Apr 12 11:13:24 [TRACE] [RT0 tx-art1.1] [cmd] invoke AgtStatisticsList GetName 419
Apr 12 11:13:24 [TRACE] [RT0 tx-art1.1]
Apr 12 11:13:24 [RT:TRACE] [tx-art1] 0 "AGT_STATISTICS_IP419"
Apr 12 11:13:24 [INFO ] [Forwarding.pm:378] stat_name is "AGT_STATISTICS_IP419"
Apr 12 11:13:24 [RT:TRACE] [tx-art1] RT->_invoke: invoke AgtStatisticsList GetName 420
Apr 12 11:13:24 [TRACE] [RT0 tx-art1.1] [cmd] invoke AgtStatisticsList GetName 420
Apr 12 11:13:24 [TRACE] [RT0 tx-art1.1]
Apr 12 11:13:24 [RT:TRACE] [tx-art1] 0 "AGT_STATISTICS_IP420"
Apr 12 11:13:24 [INFO ] [Forwarding.pm:378] stat_name is "AGT_STATISTICS_IP420"
Apr 12 11:13:24 [INFO ] [Forwarding.pm:446] R0 POST TEST MEASUREMENTS FOR
REFERENCE CONFIG
Apr 12 11:13:24 [TRACE] [R0 mohawk] [cmd] show chassis routing-engine
Apr 12 11:13:24 [TRACE] [R0 mohawk] Routing Engine status:
Apr 12 11:13:24 [TRACE] [R0 mohawk] Slot 0:
Apr 12 11:13:24 [TRACE] [R0 mohawk] Current state Master
Apr 12 11:13:24 [TRACE] [R0 mohawk] Election priority Master (default)
Apr 12 11:13:24 [TRACE] [R0 mohawk] Temperature 33 degrees C / 91 degrees F
Apr 12 11:13:24 [TRACE] [R0 mohawk] CPU temperature 34 degrees C / 93
degrees F
Apr 12 11:13:24 [TRACE] [R0 mohawk] DRAM 2048 MB
Apr 12 11:13:24 [TRACE] [R0 mohawk] Memory utilization 21 percent
Apr 12 11:13:24 [TRACE] [R0 mohawk] CPU utilization:
Apr 12 11:13:24 [TRACE] [R0 mohawk] User 0 percent
Apr 12 11:13:24 [TRACE] [R0 mohawk] Background 0 percent
Apr 12 11:13:24 [TRACE] [R0 mohawk] Kernel 3 percent
Apr 12 11:13:24 [TRACE] [R0 mohawk] Interrupt 0 percent
Apr 12 11:13:24 [TRACE] [R0 mohawk] Idle 97 percent
Apr 12 11:13:24 [TRACE] [R0 mohawk] Model RE-4.0
Apr 12 11:13:24 [TRACE] [R0 mohawk] Serial ID P11123907179
Apr 12 11:13:24 [TRACE] [R0 mohawk] Start time 2007-04-10 15:49:21 PDT
Apr 12 11:13:24 [TRACE] [R0 mohawk] Uptime 1 day, 19 hours, 24 minutes
Apr 12 11:13:24 [TRACE] [R0 mohawk] Load averages: 1 minute 5 minute 15
minute
Apr 12 11:13:24 [TRACE] [R0 mohawk] 0.04 0.04 0.00
Apr 12 11:13:24 [TRACE] [R0 mohawk] Routing Engine status:
Apr 12 11:13:24 [TRACE] [R0 mohawk] Slot 1:
Apr 12 11:13:24 [TRACE] [R0 mohawk] Current state Backup
Apr 12 11:13:24 [TRACE] [R0 mohawk] Election priority Backup (default)
Apr 12 11:13:24 [TRACE] [R0 mohawk] Temperature 32 degrees C / 89 degrees F
Apr 12 11:13:24 [TRACE] [R0 mohawk] CPU temperature 32 degrees C / 89
degrees F
Apr 12 11:13:24 [TRACE] [R0 mohawk] DRAM 2048 MB
Apr 12 11:13:24 [TRACE] [R0 mohawk] Memory utilization 14 percent
Apr 12 11:13:24 [TRACE] [R0 mohawk] CPU utilization:
Apr 12 11:13:24 [TRACE] [R0 mohawk] User 0 percent
Apr 12 11:13:24 [TRACE] [R0 mohawk] Background 0 percent
Apr 12 11:13:24 [TRACE] [R0 mohawk] Kernel 0 percent
Apr 12 11:13:24 [TRACE] [R0 mohawk] Interrupt 0 percent
Apr 12 11:13:24 [TRACE] [R0 mohawk] Idle 100 percent
<continues here>
perldoc perldebug
NAME
perldebug - Perl debugging
DESCRIPTION
First of all, have you tried using the -w switch?
$ perl -d -e 42
The program will halt right before the first runtime executable
statement (but see below regarding compile-time statements) and ask you
to enter a debugger command. Contrary to popular expectations, whenever
the debugger halts and shows you a line of code, it always displays the
line it’s about to execute, rather than the one it has just executed.
For any text entered at the debugger prompt, leading and trailing
whitespace is first stripped before further processing. If a debugger
command coincides with some function in your own program, merely precede
the function with something that doesn’t look like a debugger command,
such as a leading ; or perhaps a +, or by wrapping it with
parentheses or braces.
<continues here>
----------------------------------------
$ perl -de 0
Data Examination: expr Execute perl code, also see: s,n,t expr
x|m expr Evals expr in list context, dumps the result or lists
methods.
p expr Print expression (uses script's current package).
S [[!]pat] List subroutine names [not] matching pattern
V [Pk [Vars]] List Variables in Package. Vars can be ~pattern or !pattern.
X [Vars] Same as "V current_package [Vars]". i class inheritance
tree.
y [n [Vars]] List lexicals in higher scope <n>. Vars same as V.
e Display thread id E Display all thread ids.
For more help, type h cmd_letter, or run man perldebug for all docs.
3. Debugger Commands
Getting out:
q Exits debugger.
R Restarts debugging session
Getting help:
h Lists help messages for all debugger commands.
hh More detailed help
hp Lists a help message for debugger command p.
Setting Breakpoints:
Breakpoints allow you to set a place where the program will stop so that you can examine
what’s going on. Once you are satisfied that at least some of the statements are executing
correctly you can let them execute automatically and stop at the parts of the program that
need to be examined more closely. You can set breakpoints at certain lines so that the
debugger stops and waits for you to issue debugger commands. There are several ways to
set breakpoints, including by line number and by line number if some condition is met (such
as a variable having a certain value). All of them are explained in the perldebug man page.
b 45 Sets break point to line 45. Type c to continue and the program will stop exe-
cution at line 45.
c Continue execution.
b greetme Sets break point to subroutine greetme.
b $x > 10 Triggers a breakpoint only if the condition is true.
w Creates a window around the breakpoint and marks the line where the break-
point is found; e.g., 10==>b (breakpoint is at line 10).
d Deletes the breakpoint on the line about to execute.
d 12 Deletes the breakpoint at line 12.
D Deletes all breakpoints.
Tracing:
T Produces a stack backtrace listing of what subroutines were called.
t Toggles trace mode.
Aliases:
= Lists all aliases.
1 $ perl -de 0
Loading DB routines from perl5db.pl version 1.28
Editor support available.
main::(-e:1): 0
2 DB<1> @colors = qw( red blue green yellow orange);
4 DB<3> X colors
$colors = 'aqua'
@colors = (
0 'red'
1 'blue'
2 'green'
3 'yellow'
4 'orange'
)
DB<4>
-------------------------------------------------------------
History command
DB<4> H
3: X colors
2: $colors = "aqua";
1: @colors = qw( red blue green yellow orange);
-------------------------------------------------------------
Listing lines and Stepping
1 perl -d random.plx
Loading DB routines from perl5db.pl version 1.28
Editor support available.
------------------------------------------------------------
Viewing arrays, hashes with X and x
(Note: You cannot view lexical(’my’) variables with X or x.)
-----------------------------------
(The Script)
#!/usr/bin/perl
1 $colors = "Prussian blue";
2 @colors = ( 'red', 'blue', 'green', 'yellow', 'orange');
3 %colors = ( "flag" => [ "red", "white", "blue" ],
"sky" => [ qw(purple red ) ],
"clothes" => { "coat"=>"blue",
"pants"=>"black",
"hat" =>"green",
},
"house" => "yellow",
);
print "The sea is $colors.\n";
print "The colors in his palette are ",join(",",@colors),".\n";
print "His hat is $colors{'clothes'}->{'hat'}.\n";
(Output)
The sea is Prussian blue.
The colors in his palette are red,blue,green,yellow,orange.
His hat is green.
4 $ perl -d debug.plx
1 'red'
4 'clothes'
5 HASH(0x189f524)
'coat' => 'blue'
'hat' => 'green'
'pants' => 'black'
6 'flag'
7 ARRAY(0x189f500)
0 'red'
1 'white'
2 'blue'
8 DB<13> x \%colors
0 HASH(0x12d2c)
'clothes' => HASH(0x189f524)
'coat' => 'blue'
'hat' => 'green'
'pants' => 'black'
'flag' => ARRAY(0x189f500)
0 'red'
1 'white'
2 'blue'
'house' => 'yellow'
'sky' => ARRAY(0x1884378)
0 'purple'
1 'red'
DB<14>
------------------------------------------------------------
Evaluating Expressions and Printing Values
Enter h or `h h' for help, or `man perldebug' for more help.
DB<6> s
main::(regex.plx:6): $pets =~ s/$2/turtle/;
DB<6> p $pets
dog, cat, bird, pig
DB<7> p $1 <-----Why so many captured in $1?
dog, cat, bird
DB<8> p $2
pig
DB<9> s
main::(regex.plx:8): print "new pet list: $pets\n";
DB<9> s
new pet list: dog, cat, bird, turtle
Debugged program terminated. Use q to quit or R to restart,
use O inhibit_exit to avoid stopping after program termination,
h q, h R or h O to get additional info. 11
----------------------------------------
1 DB<1> s
main::(random.plx:10): randomize(\@sayings);
2 DB<1> n <------Jump over subroutine statements
1
A stitch in time
2
Too many cooks
0
An apple a day
2
Too many cooks
Debugged program terminated. Use q to quit or R to restart,
use O inhibit_exit to avoid stopping after program termination,
h q, h R or h O to get additional info.
DB<1> s
main::(random.plx:10): randomize(\@sayings);
DB<1> s
main::randomize(random.plx:13): my $ptr = shift;
DB<1> s
main::randomize(random.plx:14): $n=0;
DB<1> s
main::randomize(random.plx:15): while ( $n < $#$ptr ){
DB<1> s
main::randomize(random.plx:16): $i= int(rand(5)) ;
DB<1> s
main::randomize(random.plx:17): print "$i\n";
DB<1> s
2
main::randomize(random.plx:18): print $ptr->[$i],"\n";
DB<1> s
Too many cooks
-------------------------------------------
Break points
DB<5> B 22
DB<6> L
random.plx:
11: randomize(\@sayings);
break if (1)
16: while ( $n < $#$ptr ){
break if (1)
DB<6> B *
Deleting all breakpoints...
--------------------------------
Pattern Matching
/pattern/ forward search for pattern
?pattern? backward search for pattern
DB<2> ?Jody
8: $ptr1->set("Name", "Jody Rogers"); # Set data for object
DB<3>
--------------------------------------
Actions
perl -d regex.plx
Tracing
11: randomize(\@sayings);
12
DB<1> s
main::(random.plx:9): print "\nNow we will print random sayings:\n";
DB<1> s
if ($arg =~ /^\-(c|f)((\-|\+)*\d+(\.\d+)*)$/) {
my ($deg, $num) = ($1, $2);
my ($in, $out) = ($num, $num);
if ($deg eq 'c') {
$deg = 'f';
$out = &c2f($num);
} else {
$deg = 'c';
$out = &f2c($num);
}
$out = sprintf('%0.2f', $out);
$out =~ s/^((\-|\+)*\d+)\.0+$/$1/;
print "$out $deg\n";
} else {
print "Usage: $0 -[c|f] num\n";
}
exit;
sub f2c {
my $f = shift;
my $c = 5 * $f - 32 / 9;
return $c;
}
sub c2f {
my $c = shift;
my $f = 9 * $c / 5 + 32;
return $f;
}