Perl is a language that I started playing with back around 1989. When I started using Perl for a project, a few people wondered if this was a good idea, given that Perl was a relatively obcure language and they worried about people knowing Perl after I left. Well, Perl has now become THE language for Unix. There are over 15 books available on Perl, a Perl magazine, and many, many web sites.
Perl was designed to be a kitchen-sink language for Unix and allows the programmer to get the same task done many ways. Perl is more expansive than AWK and you can get a lot more done, although some AWK programs will be shorter than Perl. If you do program in AWK and wish to convert to Perl, there is a nice AWK-to-Perl program that comes with the Perl distribution.
To show how different AWK is from Perl, let’s use the same example programs as above, but write them in Perl. The first Perl program is the same as the first AWK program. Note how many more lines it takes in Perl. I’m sure this Perl program is not the most optimal, but even an optimal Perl program would be longer than the 2 line AWK program. Here is the program in Perl:
rep1_pl:
#!/usr/bin/perl
# Read the file into an array
open(FILE,"test_data");
@array = <FILE>;
close(FILE);
foreach $line (@array) {
@array2 = split(/:/,$line);
print "$array2[2]";
}
And the output is:
bob@mail.com rj@newmail.com john@oldmail.com trw@mail.com
The first line of a Perl program starts with #!/usr/bin/perl, or something like that. This is not a part of the Perl program, but is used to tell the Unix shell to run Perl and feed it the rest of the script. It is not needed for the QL version of Perl.
With the second report, I decided to use the ‘format’ feature of Perl. It allows you to define fields so that the output can be formated into neat columns. Left and right justification and the decimal point can be handled for you. It can take a while to get used to formats, but once you do you find them usefull for all sorts of tasks. Here is the 2nd script:
#!/usr/bin/perl
#Define formated output
format TOP =
Name E-Mail Address
------------------------------------------
.
format STDOUT =
@<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<
$name, $email
.
format BOTTOM =
------------------------------------------
Total Addresss = @<<<<
$count
.
# Read the file into an array
open(FILE,"test_data");
@array = <FILE>;
close(FILE);
$^ = TOP;
$~ = STDOUT;
$count = 0;
foreach $line (@array) {
@array2 = split(/:/,$line);
$name = $array2[1]." ".$array2[0];
$email = $array2[2];
write;
$count = $count + 1;
}
$~ = BOTTOM;
write;
Name E-Mail Address
------------------------------------------
Bob Andrews bob@mail.com
Ralph Johnson rj@newmail.com
John Smith john@oldmail.com
Ted Wilson trw@mail.com
------------------------------------------
Total Addresss = 4
As another example, here is a program that I wrote to figure out the odds on die rolls.
#!/usr/bin/perl
#
# dice_pl
#
# This program determines the percentages in rolling X
number
# of Y sided dice. The simplest approach to doing this is
# to do a something like this (for 2 6-sided die):
#
# FOR x = 1 to 6
# FOR y = 1 to 6
# roll = x + y
# NEXT y
# NEXT x
#
# But this means that the number of dice used is hard coded
# into the program. This programs approach is like an
# odometer. An array is used that is equal to the number of
# die used. The first die is incremented and each other
# die is incremented when the one next to each reaches 7
# (still using the 2 6-sided die example).
#
# Here is a visual diagram:
#
# ------------------------
# | 1 | 1 | 1 | 1 |
# ------------------------
#
# Once the first "die" hits 7, it goes back to 1 and the
# "die" next to hit rolls over to 2. This continues until
# all possible combinations have been made.
#
# Output is :
# Die Roll - the value of the die.
# Possible - how many times this die roll can occur.
# % of Roll - Percentage of total rolls that this roll
# can occur.
# To-Hit % - Percent chance of making rolling this
number
# or less.
format top =
Die Roll Possible % of Roll To-Hit %
--------------------------------------------
.
format STDOUT =
@### @### @###.## @###.##
$x,$rolls,$indper,$totper
.
die "Usage: dice.pl die_sides num_die\n" if @ARGV < 2;
$num_die = $ARGV[1];
$sides = $ARGV[0];
print "\n Roll of $num_die $sides-Sided Die\n";
# set all dice to 1
for ( $x = 1; $x <= $num_die; $x++) {
$array[$x] = 1;
}
$array[1] = 0;
for ( $y = 1; $y <= $sides**$num_die; $y++ ) {
#Increment the first die
$array[1] = $array[1] + 1;
$total = 0;
# Go through each die and see if they need to "rollover"
# then calculate total of dice.
for ($x = 1; $x <= $num_die; $x++) {
if ( $array[$x] == $sides+1 ) {
$array[$x] = 1;
$array[$x+1] = $array[$x+1] + 1;
}
$total = $total + $array[$x];
}
$total_array[$total] = $total_array[$total] + 1;
}
# Report Section
# Output is
# - Die Roll Of (total of dice)
# - Number of Times Possible
# - % of that Roll
# - % of To-Hit number
$total = 0;
for ($x = $num_die; $x <= $sides*$num_die; $x++) {
$rolls = $total_array[$x];
$indper = ($total_array[$x]/$sides**$num_die)*100;
$total = $total + $total_array[$x];
$totper = ($total/$sides**$num_die)*100;
write;
# print("Die Roll of $x,$total_array[$x], $temp1,
$temp2\n");
}
When using Perl, remember that there is no “shell” in QDOS. In the standard Perl use, there are a couple of different ways to have Perl run an OS command, like DEL in MS-DOS or ‘rm’ in Unix. To do this, Perl executes the operating system shell and passes to it the command to execute. This works for real executables or internal shell commands. In QDOS these “shell” calls work out to be really nothing more than an EXEC, or EXEC_W call. There is no way to have Perl run a QDOS/SuperBasic imbedded command, like ‘wdir’.
Here is an example:
system("ls");
This works out the the QDOS command of:
EXEC_W ls
The Perl command:
system("unzip file_zip");
works out to the QDOS command of:
EXEC_W unzip;"file_zip"
So if the following Perl command:
system("dir flp1_");
works out to the QDOS command of:
EXEC_W dir;"flp1_"
which is invalid.
On the QL, the back tick character is really the Pound Sterling symbol (which, for portablilty reasons I won’t show here). This means that if you take a Perl program written on another system and bring it to the QL, all of the back tick characters will show up as the Pound Sterling character. This also means that if you are writting a Perl program on the QL, use the Pound Sterling character and it will be treated as a back tick. Since the two characters have the same ASCII value, you don’t need to worry about converting, by hand, the two characters, as it will happen automatically.
Where this is important in Perl, is in the following command:
@array = `ls bin*`;
Having a string in back ticks (versus single or double quotes), tells Perl to execute what is in between the back ticks. This is the same convention used in the Unix C Shell scripting language.
If you are looking for books on Perl, remember that Perl for QDOS is Perl Version 4 and most books deal with Perl Version 5. The first edition of “Programming Perl” and “Learning Perl” (red binding) dealt with Perl Version 4. There are some major changes between Perl 4 and Perl 5, including some syntax changes in common functions.