This tutorial walks through using array variables in Perl.
Simple Arrays
You¡¯ve already seen simple arrays. We used them for the ¡°command line¡± variables. Simple arrays begin with the ¡°@¡± symbol. If you want a specific value from the array, you index that value using its number in the array. If you want the first item from the array, you ask for ¡°$ARGV[0]¡±. If you want the third item, use ¡°$ARGV[2]¡±.
Arrays always use the ¡°@¡± symbol. Scalar variables always use the ¡°$¡± symbol. A piece of an array is always a scalar. (You can¡¯t have arrays inside of arrays in simple Perl.) That's why you use ¡°@¡± to refer to the entire array, and ¡°$¡± to refer to items within the array. If you want to know how many values are in an array, use the scalar variable $#ARRAY. This is actually the index of the last element, so for the count, you¡¯ll need to add one. For example:
@Names = ("John","Jerry","Steve","Hsiao-Ping","Daniel");
$NameCount = $#Names+1;
print "There are $NameCount names in the array.\n";
foreach $Counter (0..$#Names) {
$HumanCounter = $Counter+1;
print "Name number $HumanCounter is $Names[$Counter].\n";
}
@Names = sort(@Names);
foreach $Name (@Names) {
print $Name;
if ($Name eq $Names[$#Names]) {
print ".\n";
} else {
print ", ";
}
}
The above program should produce the following:
/u5/jerry> arraytest
There are 5 names in the array.
Name number 1 is John.
Name number 2 is Jerry.
Name number 3 is Steve.
Name number 4 is Hsiao-Ping.
Name number 5 is Daniel.
Daniel, Hsiao-Ping, Jerry, John, Steve.
Can you spot a possible problem in the above program? You¡¯d better, because fixing it is going to be an exercise!
Shifting Array Values
You will often shift array values when you are pulling command line options from a command line that can also include filenames. In general on Unix, when a command takes both options and filenames as arguments, the filenames come last. The ¡®shift¡¯ function allows you to slide the first element of the array out from under the rest of the elements. It completely removes that element from the array.
while ($ARGV[0] =~ /^-/) {
$currentArg = shift(@ARGV);
#figure out which option this is
#blah blah
}
#go ahead and do the rest on the filenames
while (<>) {
print;
}
Getting a Numeric Array
Suppose you want an array of numbers from 5 to 1000. You could construct it by hand, but Perl will make it for you. We¡®ve already done it once with ¡°foreach¡±:
@Counters = (5..1000);
This numeric construction always counts up by one. If you want to count down instead of up, you can reverse the array:
@Counters = reverse(@Counters);
or, you could combine it into one line with
@Counters = reverse(5..1000);
Sorting Arrays
You can sort arrays using simple or complex methods. The simplest way to sort an array is to use the sort function:
@Names = sort(@Names);
Sort always sorts in alphabetical order. If you want to sort in numerical order, you need to use the more complex version:
@Numbers = sort numerically @ARGV;
sub numerically {
return $a <=> $b;
}
In this case, we¡¯re telling ¡®sort¡¯ to use the ¡®subroutine¡¯ numerically to determine how to sort the array. A ¡®subroutine¡¯ is a bit of code that can be reused without having to retype it. In this case, a sort subroutine is a special subroutine that has its arguments automatically put into $a or $b. The subroutine must return an integer. If this integer is less than zero, sort assumes that $a comes before $b. If this integer is greater than zero, sort assumes that $b comes before $a. If the integer is zero, sort assumes it doesn¡¯t matter.
The operator ¡®<=>¡® returns -1 if the item on the left is less than the item on the right, zero if they¡¯re equal, and 1 if the item on the right is less than the item on the left. Go ahead and test it:
print $ARGV[0] <=> $ARGV[1];
print "\n";
You can do whatever you want in your subroutine, as long as it returns predictable integer values based on $a and $b.
The equivalent to ¡®<=>¡® for strings is ¡®cmp¡¯. Go ahead and replace ¡®<=>¡® above with ¡®cmp¡¯ and try different strings on the command line.
Other Array Functions
| Function | Result |
| join(@array,$string) | returns the elements of array using string as a delimiter |
| pop(@array) | returns and removes the last element of array |
| push(@array,$string) | puts string onto the end of array. Does not return ¡®array¡¯. |
| shift(@array) | returns and removes the first element of array |
| split($string1,$string2) | returns string2 split into an array wherever string1 occurs |
Associative Arrays
Associative arrays start tapping into the database functions of Perl. An associative array is a list of elements, but each element in the array is accessed by an index value that does not have to be a number.
$LastNames{'Jerry'} = 'Stratton';
$LastNames{'John'}='Paul';
$LastNames{'Steve'}='Spear';
print $LastNames{$ARGV[0]};
print "\n";
This array stores the values ¡°Stratton¡±, ¡°Paul¡±, and ¡°Spear¡±. In order to access those values, I need to know the value they¡¯re associated with:
20: lastname Jerry
Stratton
21: lastname Steve
Spear
You¡¯ll use the ¡°delete¡± function to delete an element of an associative array:
$deletedName = delete $LastNames{'Steve'};
If you need to get a list of all the keys in an associative array, use the keys function:
@FirstNames = keys(%LastNames);
foreach $key (@FirstNames) {
print "$key: $LastNames{$key}\n";
}
Like scalar variables and simple arrays, associative arrays have their own prefix, the ¡°percent¡± sign. Like simple arrays, you¡¯ll only use the percent sign when referring to the associative array as a whole. When referring to individual elements, you¡¯ll continue to use the dollar sign.
Let¡¯s take a look at a simple program for viewing the passwd file in Unix:
$PASSWDFILE = '/var/yp/passwd';
open PASSWDFILE;
while (<PASSWDFILE>) {
@lineItems = split(':');
$username = $lineItems[0];
$passwords{$username} = $lineItems[1];
$userids{$username} = $lineItems[2];
$groupids{$username}=$lineItems[3];
$names{$username}=$lineItems[4];
$homes{$username}=$lineItems[5];
$shells{$username}=$lineItems[6];
}
close PASSWDFILE;
foreach $User (@ARGV) {
$User = lc($User);
print uc($User);
print ":\n";
print "\tPassword: $passwords{$User}\n";
print "\tUser ID: $userids{$User}\n";
print "\tGroup ID: $groupids{$User}\n";
print "\tReal Name: $names{$User}\n";
print "\tHome Directory: $homes{$User}\n";
print "\tDefault Shell: $shells{$User}\n";
print "\n";
}
This script uses usernames as the ¡®key¡¯ for this associative array. It could just as well have used user id. The key has to be something that will be unique for each ¡®record¡¯.
Note that in the ¡®split¡± line, we¡¯ve left out the $_. Perl will often assume that that¡¯s what you meant, and in this case it works just fine.
We¡¯ve also explicitly opened a file here for the first time. We¡¯ll have more on that later, but we put the filename into a scalar variable, and made sure that scalar variable was in all capitals. This allowed us to use the simple form for opening the filename contained in that variable. And don¡¯t forget that we closed it at the end! If you look at the ¡®while¡¯, you¡¯ll see that it looks pretty much the same as when we used the <STDIN> filehandle.
About this Tutorial
This tutorial is written by Jerry Stratton and is published under the GNU Free Documentation License.
discuss this topic to forum
