Goals
In this session you will:
- manipulate <STDIN> in an @array context
- manipulate command line arguments
- look at the major control structures
- manipulate $scalars, @arrays, and %hashes and their elements
- open, manipulate, lock, and close filehandles
- open, read, and close directory handles
Review
POST
- What should be on the first line of your script?
- Is there a useful switch that shows you verbose warnings?
- How is an @array different from a %hash?
- Extra Credit: How do permissions on scripts differ from permissions on binary executables?
manipulate <STDIN> in an @array context
We have already read in a single line of STDIN into a $scalar thusly: $input = <STDIN>;
We can do a similar thing by reading the input into an @array context: @input = <STDIN>;
The method of getting the actual input into the array differs a bit, as this context expects several lines terminated by an EOF marker [CTRL-D]. You can do this manually or pipe the text to your script.
manipulate command line arguments
Perl has a special @array to hold command line arguments: @ARGV .
The actual scriptname, as called, is stored in $0 like shell scripts do.
One element per argument. myscript.pl first second third would yield:
$0 would contain "myscript.pl"
@ARGV would contain the entire array of passed args
$ARGV[0] would contain "first"
$ARGV[1] would contain "second"
$ARGV[2] would contain "third"
$#ARGV would contain the subscript of the last element
If your script requires a certain amount of args to run properly, remember to check for that number or error out with help.
- verify that ($#ARG + 1) >= (minimum args)
- or... check for the existence of $ARGV[$min - 1]
You can also use an interesting function of the @ARGV array to specify files as sources for STDIN: pass them on the command line and then use bizarre-looking diamond operator <> in a loop. See p 73 in your text for more info.
Control structures
if/unless
if (true_expression) {
do your thing;
}
elsif (some_other_expression) {
another thing;
}
else {
final option;
}
while/until
while (true_expression) {
do this;
}
Remember to change the evaluated expression or you'll have an endless loop. You can use the do/while syntax to evaluate after the action. Like incrementing++ v. ++incrementing
for
for (starting_value; evaluation; re-initialize value) {
do this;
}
*foreach*
foreach $temp (@array/list) {
do this with $temp;
}
Misc
manipulate $scalars, @arrays, and %hashes.
$scalars
- chop() and chomp()
- forcing uppercase, lowercase character or word
- substr(var, offset [, length])
- split(/[delimiter]/, $scalar)
- join('[delimiter]', [list or @array]) (use pack and unpack for fixed-length binary fields)
- substitution: $var =~ s/[regex]/[replacement]/gi
- matching: $var =~ /[regex]/
@arrays
- sort()
- rev() also works on scalars
- push(@array, list) onto end of stack, pop(@array) from end of stack
- shift(@array) from front of stack, unshift(@array, list) from front of stack
- splice() for more complex stack operations
- array slices @array[element..element]
%hashes
- keys(%hash) returns keys as an @array
- values(%hash) returns values (might not be unique)
- each(%hash), returns a two-element hash with each iteration
while (($key,$value) = each (%hash)) from pp 160 of the camel book
open, manipulate, lock, and close filehandles
There are two general ways to get info out of files:
-
- slurp the whole file up, close the filehandle and work with the whole thing in memory (small files, frequent accesses, unstable system)
- hold the filehandle open while you iterate through it (larger files, less frequent "hits", stable system)
open the file handle
open(FILEHANDLE, [mode]file);
open(DATA, "</home/jason/clients.txt"); #open for input
open(DATA, "/home/jason/clients.txt"); #same!
open(DATA, ">/home/jason/clients.txt"); #open for output
open(DATA, ">>/home/jason/clients.txt"); #open for append
open(DATA, "+>/home/jason/clients.txt"); #read and write; seek();
An idiomatic example
#define mnemonics for lock
$FLOCK_SHARED=1;
$FLOCK_EXCLUSIVE=2;
$FLOCK_NOFAIL=4; #don't wait, even if you can't
$FLOCK_RELEASE=8;
#set a $scalar with the filename in it for convenience
$filename="/home/jason/clients.txt";
#open the file or die trying
#note use of the $! special var that indicates OS error
open(DATA, ">>$filename") or
die ("could not open $filename: $!");
#get an exclusive lock
flock(DATA, $FLOCK_EXCLUSIVE);
#do your business here
# YOUR CODE HERE
# like print DATA ("This is some new information.\n");
#close the filehandle
#automagically releases the advisory lock
close(DATA);
open, read, and close directory handles
opendir(DATADIR, "$somedir") or die $!;
@allfiles=readdir(DATADIR);
- from the camel book. Avoid the "." and ".." files thusly:
@allfiles=grep (!/^\.\.?$/, readdir(DATADIR) );
closedir(DATADIR);
You can't lock a directory! :-)
open, close named pipes
You can open a named pipe (a | that you can attach a HANDLE to) and send information to it. The
idiomatic example is a named pipe to a mail program.
$mailprog="/usr/lib/sendmail -t";
open(MAIL, "|$mailprog") or die $!;
#this is a "here" document
print MAIL <<end;
To: $some_fellow
From: $my_email
Subject: Check this out!
$message
end
#the marker needs to be against the left margin, even if this is an indented loop
close(MAIL); #the mail goes out!
Homework
If your eyeballs still work after all that, pls read the following info for our next class
- report formatting 116-128
- special printing formats
- subroutines
- scope
http://www.mousetrap.net/introperl/day2.html
$Id: day2.orb,v 1.3 2002/04/14 14:59:39 mouse Exp $