[Chapter 1] 1.3 A Grade Example
Author: Larry Wall, Tom Christiansen & Randal L. Schwartz
Date: 1999-07-02T01:29:12Z

#

| Chapter 1 An Overview of Perl |

## 1.3 A Grade Example

Suppose you had a set of scores for each member of a class you are teaching. You'd like a combined list of all the grades for each student, plus their average score. You have a text file (imaginatively named grades) that looks like this:

    Noël 25
    Ben 76
    Clementine 49
    Norm 66
    Chris 92
    Doug 42
    Carol 25
    Ben 12
    Clementine 0
    Norm 66
    ...

You can use the following script to gather all their scores together, determine each student's average, and print them all out in alphabetical order. This program assumes, rather naively, that you don't have two Carols in your class. That is, if there is a second entry for Carol, the program will assume it's just another score for the first Carol (not to be confused with the first Noël).

By the way, the line numbers are not part of the program, any other resemblances to BASIC notwithstanding.

     1  #!/usr/bin/perl
     2
     3  open(GRADES, "grades") or die "Can't open grades: $!\n";
     4  while ($line = <GRADES>) {
     5      ($student, $grade) = split(" ", $line);
     6      $grades{$student} .= $grade . " ";
     7  }
     8
     9  foreach $student (sort keys %grades) {
    10      $scores = 0;
    11      $total = 0;
    12      @grades = split(" ", $grades{$student});
    13      foreach $grade (@grades) {
    14          $total += $grade;
    15          $scores++;
    16      }
    17      $average = $total / $scores;
    18      print "$student: $grades{$student}\tAverage: $average\n";
    19  }

Now before your eyes cross permanently, we'd better point out that this example demonstrates a lot of what we've covered so far, plus quite a bit more that we'll explain presently. But if you let your eyes go just a little out of focus, you may start to see some interesting patterns. Take some wild guesses now as to what's going on, and then later on we'll tell you if you're right.

We'd tell you to try running it, but you may not know how yet.

### 1.3.1 How to Do It

Gee, right about now you're probably wondering how to run a Perl program. The short answer is that you feed it to the Perl language interpreter program, which coincidentally happens to be named perl (note the case distinction). The longer answer starts out like this: There's More Than One Way To Do It.[13]

> [13] That's the Perl Slogan, and you'll get tired of hearing it, unless you're the Local Expert, in which case you'll get tired of saying it. Sometimes it's shortened to TMTOWTDI, pronounced "tim-toady". But you can pronounce it however you like. After all, TMTOWTDI.

The first way to invoke perl (and the way most likely to work on any operating system) is to simply call perl explicitly from the command line. If you are on a version of UNIX and you are doing something fairly simple, you can use the -e switch (`%` in the following example represents a standard shell prompt, so don't type it):

    % perl -e 'print "Hello, world!\n";'

On other operating systems, you may have to fiddle with the quotes some. But the basic principle is the same: you're trying to cram everything Perl needs to know into 80 columns or so.[14]

> [14] These types of scripts are often referred to as "one-liners". If you ever end up hanging out with other Perl programmers, you'll find that some of us are quite fond of creating intricate one-liners. Perl has occasionally been maligned as a write-only language because of these shenanigans.

For longer scripts, you can use your favorite text editor (or any other text editor) to put all your commands into a file and then, presuming you named the script gradation (not to be confused with graduation), you'd say:

    % perl gradation

You're still invoking the Perl interpreter explicitly, but at least you don't have to put everything on the command line every time. And you don't have to fiddle with quotes to keep the shell happy.

The most convenient way to invoke a script is just to name it directly (or click on it), and let the operating system find the interpreter for you. On some systems, there may be ways of associating various file extensions or directories with a particular application. On those systems, you should do whatever it is you do to associate the Perl script with the Perl interpreter. On UNIX systems that support the `#!` "shebang" notation (and most UNIX systems do, nowadays), you can make the first line of your script be magical, so the operating system will know which program to run. Put a line resembling[15] line 1 of our example into your program:

> [15] If perl isn't in /usr/bin, you'll have to change the `#!` line accordingly.

    #!/usr/bin/perl

Then all you have to say is

    % gradation

Of course, this didn't work because you forgot to make sure the script was executable (see the manpage for chmod(1))[16] and in your PATH. If it isn't in your PATH, you'll have to provide a complete filename so that the operating system knows how to find your script. Something like

> [16] Although Perl has its share of funny notations, this one must be blamed on UNIX. chmod(1) means you should refer to the manpage for the chmod command in section one of your UNIX manual. If you type either `man 1 chmod` or `man -s 1 chmod` (depending on your flavor of UNIX), you should be able to find out all the interesting information your system knows about the command chmod. (Of course, if your flavor of UNIX happens to be "Not UNIX!" then you'll need to refer to your system's documentation for the equivalent command, presuming you are so blessed. Your chief consolation is that, if an equivalent command does exist, it will have a much better name than chmod.)

    % ../bin/gradation

Finally, if you are unfortunate enough to be on an ancient UNIX system that doesn't support the magic `#!` line, or if the path to your interpreter is longer than 32 characters (a built-in limit on many systems), you may be able to work around it like this:

    #!/bin/sh -- # perl, to stop looping
    eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
        if 0;

Some operating systems may require variants on this to deal with /bin/csh, DCL, COMMAND.COM, or whatever happens to be your default command interpreter. Ask your Local Expert.

Throughout this book, we'll just use `#!/usr/bin/perl` to represent all these notions and notations, but you'll know what we really mean by it.

A random clue: when you write a test script, don't call your script test. UNIX systems have a built-in test command, which will likely be executed instead of your script. Try try instead.

A not-so-random clue: while learning Perl, and even after you think you know what you're doing, we suggest using the -w option, especially during development. This option will turn on all sorts of useful and interesting warning messages, not necessarily in that order. You can put the -w switch on the shebang line, like this:

    #!/usr/bin/perl -w

Now that you know how to run your own Perl program (not to be confused with the perl program), let's get back to our example.

1.2 Natural and Artificial Languages |  | 1.4 Filehandles