Getting started with Perl, Part 1

An introduction to the language that "can do anything"

Summary
Perl can often offer a simple solution when writing a program that can be painfully difficult in shell script. In part one of this two-part series, Mo walks you through an introduction to the popular scripting language with some illustrative examples. (2,800 words)


The Perl lobby has been strong and consistent, so it is high time for me to provide an introduction to this language.

What is Perl? In the O'Reilly & Associates book Programming Perl, by Larry Wall (the developer of the Perl language), Tom Christiansen, and Randal L. Schwartz, the preface describes Perl as a programming language "that makes it easy to manipulate numbers and text, files and directories, computers and networks."

I quote from the developer of Perl here to defend myself in advance. There are Perl fanatics out there who will tell you that anything that you can say about what the language does is too limiting, since it can do anything better than any other language.

Perl is indeed a very nifty programming language and is easier to use than shell programming languages. It can be used to replace any shell program, and except in very simple cases, it does a much better job (and is easier to understand) than the shell version of the same thing. It certainly fulfills its promise of easy handling of text, numbers, and files.

It's also very flexible. In fact, the motto for Perl is "There's More Than One Way To Do It." I am well aware that in the following examples nearly every line of code could be written in about half a dozen different ways, but this is simply meant as an introduction. If you are a Perl expert and you feel there is a better way to do one of these tasks, you may well be right. Please be patient.

If you do not have Perl on your system, then you should install it. It is available by starting at http://www.perl.com/, the Perl home page on the Web.

I have chosen a simple but illustrative project to begin with, which is easy in Perl, but devilishly difficult in shell script. This project will maintain and allow lookups in a simple text file database of names and addresses. We'll need more than one installment, so let's get started.

If you are familiar with shell programming, then you have a head start on Perl. I'll start with the traditional greeting program. The print command prints a string and the \n indicates a new line in the printed string. Perl commands end with a semi-colon. You can run this Perl script by saving it as hello and typing perl hello.

print "Yo, Adrian!\n";

A somewhat more informative version of the program adds the shebang method of launching. If your shell supports the shebang syntax then you can identify the program that will be used to execute the script as shown in the first line of the following example. Save this script as hello, set its execute mode with chmod a+x hello, and then type hello to start the program. If your shell does not support shebang, you can still start the program by typing perl hello.

#!/usr/bin/perl
print "Yo, Adrian!\n";

Subroutines and functions
Perl supports subroutines or functions and does not differentiate between the two. Subroutines are very common in Perl programs. The following listing produces the same greeting by using a subroutine. Line numbers are included for explanation.

Lines 4 through 7 define a subroutine named say_hello that prints the message on the screen. Line 2 calls the subroutine. Perl is smart enough to know that the program ends at line 3, after it has called say_hello, and does not attempt to execute say_hello a second time. However, it is always good practice to provide a clear exit in your programs, and line 3 could contain exit(0) without affecting the behavior of the program.

1	#!/usr/bin/perl
2	say_hello();
3	
4	sub say_hello
5	{
6		print "Yo, Adrian!\n";
7	}

Perl variables can be created and assigned on the fly. They begin with a dollar sign ($), much like shell variables. At line 6, the value is first assigned to a variable, and then the variable is printed with an appended newline. Note that the syntax of the print command allows the variable $x to appear inside the quotes.

1	#!/usr/bin/perl
2	say_hello();
3	
4	sub say_hello
5	{
6		$x="Yo, Adrian";
7		print "$x\n";
8	}

A more unique and very useful variable in Perl is the list (or array) variable. List variables begin with the at sign (@) and are an array of individual variables. The following listing presents two different ways of loading a list variable, and three different ways of accessing and printing them.

At lines 9 through 14, the individual elements of the array are initialized. At lines 15 through 18, the array is loaded with a comma-separated list of values. Accessing the variables is even more flexible. Lines 20 through 26 print each individual array element with spaces and newlines. Lines 27 through 31 assign the values in the list variable to individual variables, by using a comma-separated list on the left-hand side of the assignment, and then prints them. Lines 32 through 35 simply print the whole list array as if it were a single variable. This technique automatically inserts a space between the individual elements of the list. You should study this example until you are comfortable with list variables. They show up a lot in Perl programs because Perl does such a great job of handling lists and arrays of values.

 1	#!/usr/bin/perl
 2	
 3	load_hello1();
 4	say_hello1();
 5	load_hello2();
 6	say_hello2();
 7	say_hello3();
 8	
 9	sub load_hello1
10	{
11		@msg[0]="Yo,";
12		@msg[1]="Adrian!";
13	}
14	
15	sub load_hello2
16	{
17		@msg=("Yo,", "Adrian!");
18	}
19	
20	sub say_hello1
21	{
22		print @msg[0];
23		print " ";
24		print @msg[1];
25		print "\n";
26	}
27	sub say_hello2
28	{
29		($yo,$name)=@msg;
30		print "$yo $name\n";
31	}
32	sub say_hello3
33	{
34		print "@msg\n";
35	}
36	

Processing files
Knowing how to process files is another basic element you will need. Perl opens files using the open function (or subroutine). The following listing opens and prints the contents of the /etc/passwd file on the terminal. This short listing covers a wealth of the options available in Perl. At line 3, the open function is used to attempt to open /etc/password and assign the open file to the file variable TEMPFILE (file variables appear in upper case by convention in Perl). If the open succeeds, then the statement after the "or" is ignored. If the open fails, the statement after the "or" -- a function called die -- is executed. The die function prints a message and exits. Embedded in the message is the special variable $!. This contains the last error message. If /etc/password couldn't be found, the printed message would be something like "Can't open /etc/passwd: The system cannot find the file specified."

At lines 5 through 8, a while loop reads input from TEMPFILE and prints it on the screen. In line 5 the Perl syntax "<TEMPFILE>" is used. The angle brackets around a file name mean "get some input from a file," in this case one line at a time. Each line is assigned to the variable $e, and then printed. When Perl reads in a line from a file, it includes the newline at the end of the line, so the print $e command at line 7 does not need to append a newline for the line to print correctly. The while test on line 5 causes the loop to continue as long as something is being read into $e from TEMPFILE. Finally at line 10 the file is closed.

1 	#!/usr/bin/perl
2 
3 	open (TEMPFILE, "/etc/passwd") or die ("Can't open /etc/passwd: $!\n");
4 
5 	while( $e=<TEMPFILE>)
6 	{
7		print $e;
8 	}
9 
10 	close TEMPFILE;

These few points cover a lot of ground, and if you are feeling lost at all, then review from the beginning, because it only gets tougher from here.

A simple database
In order to implement a simple database, we are going to start with a simple menu. This menu will be the front end that drives the different actions on the address book such as adding an address or looking up an address. The menu will be defined in a text file containing 3 fields: the letter to press to invoke a menu action, the prompt displayed to describe the menu action, and the command to execute when that selection is made. An example of a simple menu file is shown below. For the moment, this file will use simple shell commands, and as the project develops we will replace these with calls to other Perl scripts. Colons separate the three fields, much like the field separator in a password file. The file is named menufile.txt. Line numbers are shown, but are not included in the file. The first menu selection will be "Say Hello Gracie" and is executed when the user types an a. The command that is executed echoes "Hello Gracie" to the screen. The second and third selections follow the same format. Create this file as menufile.txt using vi or another editor.

1 	a:Say Hello Gracie:echo "Hello Gracie"
2 	b:Show Perl man pages:man perl
3 	c:Show Current Directory:ls -l|more

We want to create a menu on the screen that looks like the following listing and executes the commands in the third field.


	a 	Say Hello Gracie
	b 	Show Perl man pages
	c 	Show Current Directory
	x 	Exit


Enter your selection

The Perl script to create this display and behavior follows. It is long and will take some studying. The main routine from lines 4 through 23 does its job by calling a series of subroutines. First, at line 8 it calls get_menu_pick(). This call will display a menu and let the user make a selection which will end up stored in $pick. At lines 14 through 18, the main loop executes the pick and then displays the menu again until the user enters an x to exit from the menu. Once the loop has ended at line 21, the screen is cleared, and finally the script exits. The get_menu_pick() subroutine at lines 29 through 34 clears the screen, displays the menu, and gets a selection from the user. The clear screen logic at 33 through 42 clears the screen by printing 25 line feeds. This is an old fashioned method, but it always works. The show_menu() logic as lines 44 through 68 includes the logic at lines 52 through 59 to open the menufile.txt and display its contents, and then close the file.

The trick line is line 55. This line uses the split function to split the $menurow that has just been read in. The split is the colon that appears as /:/ in the command. This command assigns everything up to the first colon, to $menupick, and everything from there up to the second colon, to $menuprompt.

($menupick, $menuprompt)=split /:/,$menurow;

At lines 56 and 57, these values are printed, and the number of lines is counted. Once the printing is done, the menu file is closed. Another line is printed containing the x/Exit option, and then some line feeds are added to the bottom of the screen to move things up so that they are more centered. Finally the screen ends with a request for the user's selection.

The get_pick() logic at 71 through 74 is very simple, but contains a new feature of Perl. Note at line 73 that a line appears to be read in from a file, STDIN, that has not been opened. In fact, Perl pre-opens several files: STDIN for standard input, STDOUT for standard output, and STDERR for standard error output. You can read from STDIN without having to open it. The results of reading from STDIN are assigned to the variable $pick, and the chomp function is used on $pick. You may remember from your earlier experience that when you read from a file, the input includes the newline. This also applies to input read from STDIN. The chomp() function provided by Perl is used to cut the trailing newline off the end of a variable to clean it up, so that after chomp($pick=<STDIN>), pick contains any characters entered, but not the newline.

At lines 76 to 91, the do_pick() routine could have been written more efficiently, but I wanted explicitly to provide another example of what Perl does best, processing text files. In do_pick() the menufile.txt file is read again, but this time all three fields in the record are pulled and stored in $menupick, $menuprompt, and $menucommand. After the read, $menucommand contains the command to be executed. The value in $menupick is compared to the value in $pick, and if it matches, the system function is used to execute $menucommand, and the logic breaks out of the while loop. The last function, press_enter(), at line 94 waits for the user to input anything and press ENTER before returning. Code this with an editor and save it as addrmenu and you can execute it either with perl addrmenu or by giving it execute privileges and starting it from a shell command.

1 	#!/usr/bin/perl
2 	
3 	
4 	#---------------------------------------
5 	# MAIN ROUTINE
6 	#---------------------------------------
7 	# Display a menu and get a selection
8 	get_menu_pick();
9 
10 	# as long as the E(x)it option is not chosen,
11 	# execute the menu option and then display
12 	# the menu again and ask for another choice
13 
14 	while ( $pick ne "x" )
15 	{
16 		do_pick();
17 		get_menu_pick();
18 	}
19 	
20 	# clear the screen and exit with a 0 return code
21 	clear_screen();
22 
23 	exit (0);
24 	#---------------------------------------
25 	# MAIN ROUTINE ENDS
26 	#---------------------------------------
27 
28 	# Clear the screen, Show the menu and get user input
29 	sub get_menu_pick
30 	{
31 		clear_screen();
32 		show_menu();
33 		get_pick();
34 	}
35 
36 	# Clear the screen by printing 25 newlines
37 	sub clear_screen
38 	{
39 		for ($i=0; $i < 25; ++$i){
40 			print "\n";
41 		}
42 	}
43 		
44 	# Open menufile.txt or exit with an error
45 	# read in each row picking up the first two fields by 
46 	# splitting it on the pipe |
47 	# print the first two fields
48 	# send some form feeds to do some centering
49 	sub show_menu
50 	{
51 		$count = 0;
52 		open( MENUFILE, "menufile.txt") or die "Can't open menufile.txt: $!\n";
53 		while ($menurow=<MENUFILE>)
54 		{
55 			($menupick,$menuprompt)=split /:/,$menurow;
56 			print "\t$menupick\t$menuprompt \n";
57 			++$count;
58 		}
59 		close MENUFILE;
60 		print "\tx\tExit\n";
61 		++$count;
62 		$count = (24 - $count ) / 2;
63 		for ($i=0; $i < $count; ++$i){
64 			print "\n";
65 		}
66 		print "\n\nEnter your selection\n";
67 
68 	}
69 
70 	# get user input and chop off the newline
71 	sub get_pick()
72 	{
73 		chomp($pick = <STDIN>);
74	}
75 
76 	sub do_pick()
77 	{
78 
79 		open( MENUFILE, "menufile.txt") or die "Can't open menufile.txt: $!\n";
80 		while ($menurow=<MENUFILE>)
81 		{
82 			($menupick, $menuprompt, $menucommand)=split /:/,$menurow;
83 			if ($menupick eq $pick)
84 			{
85 				system $menucommand;
86 				break;
87 			}
88 		}
89 		close MENUFILE;
90 		press_enter();
91 	}
92 
93 	# put up a message and wait for user to press ENTER
94 	sub press_enter
95 	{
96 		print "Press Enter to Continue . . .\n";
97 		$dummy = <STDIN>;
98 	}
99 

Some things are worthy of note in addrmenu. At lines 14 and 83 there are comparisons made against string values. One example uses "ne" and the other uses "eq". Perl makes a distinction between numeric and string data. Even though a variable could be named $some_number it could be assigned a totally non-numeric value as in $some_number = "Hello". In order to make this difference clear, Perl uses separate operators including comparison operators for numbers and strings. Numbers use the traditional ==, !=, <, >, and <= while string comparisons use eq, ne, lt, gt, and le.

Another element to note is the calling conventions for functions. Function arguments do not have to be enclosed in parentheses, thus the following two lines are equivalent, but the second is more readable, looking almost like English.

open( MENUFILE, "menufile.txt") or die ("Can't open menufile.txt: $!\n");
open MENUFILE, "menufile.txt" or die "Can't open menufile.txt: $!\n";

However, sometimes the parentheses clarify what is happening, as in the following the example where a line is read in from STDIN and assigned to $pick, and then chomp is used on $pick to lop off the newline at the end.

chomp($pick = <STDIN>);

In the next installment we will look at other file activities, including writing to a file, and explore further features of Perl.

Contact us for a free consultation.

 

MENU:

 
SOFTWARE DEVELOPMENT:
    • EXPERIENCE
PRODUCTS:
UNIX: 

   • UNIX TUTORIALS

LEGACY SYSTEMS:

    • LEARN COBOL
    • PRODUCTS
    • GEN-CODE
    • COMPILERS   

INTERNET:
    • CYBERSUITE   
WINDOWS:

    • PRODUCTS


Search Now:
 
In Association with Amazon.com

Copyright©2001 King Computer Services Inc. All rights reserved.