📄 ch5.htm
字号:
<HTML>
<HEAD>
<TITLE>Chapter 5 -- Perl Scripts for Windows NT</TITLE>
<META>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#CE2910">
<H1><FONT SIZE=6 COLOR=#FF0000>Chapter 5</FONT></H1>
<H1><FONT SIZE=6 COLOR=#FF0000>Perl Scripts for Windows NT</FONT>
</H1>
<HR>
<P>
<CENTER><B><FONT SIZE=5><A NAME="CONTENTS">CONTENTS</A></FONT></B></CENTER>
<UL>
<LI><A HREF="#SortingProcedures">
Sorting Procedures</A>
<UL>
<LI><A HREF="#SearchinganArray">
Searching an Array</A>
<LI><A HREF="#ProcessingProcedures">
Processing Procedures</A>
<LI><A HREF="#BasicProceduresinPerl">
Basic Procedures in Perl</A>
</UL>
<LI><A HREF="#MiscellaneousProcedures">
Miscellaneous Procedures</A>
<UL>
<LI><A HREF="#ProcessingAlltheElementsofanAssociativeArray">
Processing All the Elements of an Associative Array</A>
</UL>
<LI><A HREF="#Conclusion">
Conclusion</A>
</UL>
</UL>
<HR>
<P>
IN the previous chapters you have gone through Perl's features
and how they will appear in a script. You have also touched on
a few uses for these features, and even tried out combinations
of these features. What you need to do now is to expand this list
of specific Perl functions to include an index of Perl code to
do regular programming duties-such as figuring out the difference
between two arrays, or finding the first array element that has
a true value. All these sections of Perl code may be inserted
into your larger scripts to perform the task specified. The Perl
procedures in this chapter either reorganize or sort data, modify
or process data, or perform some other miscellaneous duty.
<H2><A NAME="SortingProcedures"><FONT SIZE=5 COLOR=#FF0000>
Sorting Procedures</FONT></A></H2>
<P>
It is often necessary to change the order of information in a
file, or generate a random number or selection of data. You can
use Perl this way to sort through the data to find information
that matches a particular parameter.
<H3><A NAME="SearchinganArray">
Searching an Array</A></H3>
<P>
You may need to search an array to find a specific element and
its index number, such as to look for the location of someone's
password or match an image to a location. To do this, try the
format shown in the listing that follows.
<BLOCKQUOTE>
<PRE>
undef $location; # creating an undefined variable
# that will hold the element's index number
for ($[ .. $#passwd) { # where @passwd is the
# array of user passwords
$location = $_, last if ($passwd[$_]); # where
# $passwd is the password entered for element
# location
}
print "$location\n" if defined($location);
</PRE>
</BLOCKQUOTE>
<H4>Printing All of an Array</H4>
<P>
This procedure is a straightforward output of an array's entire
contents, separated by an arbitrary string. You could use this
procedure to return a list of user form requests to confirm their
order, separating them with HTML tags and new line commands. The
format takes two forms, shown in the following two listings.
<BLOCKQUOTE>
<PRE>
print join($separator, @array_name), $terminator;
</PRE>
</BLOCKQUOTE>
<P>
or
<BLOCKQUOTE>
<PRE>
{
local($,,$/) = ($separator, $terminator);
print @array_name;
}
</PRE>
</BLOCKQUOTE>
<P>
where in both cases the variable $separator has the value of the
separator string. Printing one element at a time (per line) requires
the use of the newline command, "/n." The terminator
string value is held in $terminator, which also requires the use
of "/n" as this string-if you want to print one element
at a time per line. This second method works best with long arrays
because it provides a temporary value for both "$" and
"$/." These variables control the array field and record
the delimiters. To have the array elements separated by only one
space, add to the final print command as shown in the next listing.
<BLOCKQUOTE>
<PRE>
print "@array_name\n";
</PRE>
</BLOCKQUOTE>
<H4> Printing All of a File to <STDOUT></H4>
<P>
To take a file and place it into <STDOUT>, follow the format
of this snippet:
<BLOCKQUOTE>
<PRE>
open(F,$file_name) || die "Unable to open $file_name: $!";
while (<F>) {
print;
}
close (F);
</PRE>
</BLOCKQUOTE>
<P>
where F is any filehandle and $file_name is a scalar variable
that holds a file name as its literal value.
<H4>Reversing a Character Line</H4>
<P>
To reverse a line of characters you can use the reverse operator:
<BLOCKQUOTE>
<PRE>
$reversed_string = reverse($frontward_string);
</PRE>
</BLOCKQUOTE>
<P>
where $reversed_string is given the reversed value of $frontward_string.
A loop in generic format for reversing anything put into <STDIN>
would be as shown as in the example below:
<BLOCKQUOTE>
<PRE>
while (<STDIN>) {
chop;
$reversed = reverse($_);
print = $reversed, "n/";
}
</PRE>
</BLOCKQUOTE>
<P>
where the contents of <STDIN> are reversed and put into
$reversed.
<H4>Reversing Words in a String</H4>
<P>
Similar to the previous procedure, you can reverse the order of
words in a string by executing the following procedure:
<BLOCKQUOTE>
<PRE>
while (<STDIN>) {
chop;
$reversed = join("",reverse split(/(\S+)/, $_));
print $reversed, "/n";
}
</PRE>
</BLOCKQUOTE>
<P>
where (\S+) tells Perl to split the words on nonwhite space, preserving
white space in the string.
<H4>Choosing an Element at Random from an Array</H4>
<P>
In <A HREF="ch7.htm" tppabs="http://210.32.137.15/ebook/PC%20Magazine%20Programming%20Perl%205.0%20CGI%20Web%20Pages%20for%20Microsoft%20Windows%20NT/ch7.htm" >Chapter 7</A>you will be creating a script that simulates a poker
game on your Web site. In order to generate a random selection
of cards, you have to be able to select a random number, in this
case from an array. To do this you can use the format as shown
below.
<BLOCKQUOTE>
<PRE>
$element = splice(@array_name, rand @array_name, 1);
</PRE>
</BLOCKQUOTE>
<P>
where the element selected from @array_name is held in $element.
To create a random selection of cards, follow the procedure shown
below.
<BLOCKQUOTE>
<PRE>
@poker_cards = 'H01'..'H13', 'D01'..'D13', 'S01'..'S13', 'C01'..'C13');
while (@poker_cards) {$poker_cards = splice(@poker_cards, rand @poker_cards, 1);
print "$poker_cards ";
print "/n" if @poker_cards % 5 >= Ø;
}
</PRE>
</BLOCKQUOTE>
<P>
where each suit of cards is divided into their 13 cards; for example,
hearts as "H01".."H13." This deals out four
poker hands of five cards each.
<H4>Shuffling an Array for Random Results</H4>
<P>
In conjunction with the previous procedure, this function will
allow you to shuffle the elements in an array, something you might
need to do in a card game program such as poker. The standard
format looks like this:
<BLOCKQUOTE>
<PRE>
local(@temp);
push(@temp, splice(@array_name, rand@array_name),1))
while @array_name;
@array_name - @temp;
</PRE>
</BLOCKQUOTE>
<P>
where @temp is the temporary array that holds the shuffled elements
of @array_name.
<P>
To use this in a poker script, shuffling an array might look like
this:
<BLOCKQUOTE>
<PRE>
@cards = 1..52;
{
local(@temp);
push(@temp, splice(@numbers, rand(@numbers), 1))
while @cards;
@cards = @temp;
}
print "@numbers\n";
</PRE>
</BLOCKQUOTE>
<P>
The 52 cards in the deck are kept in @cards, and the shuffled
cards are kept in @temp. Instead of using the print statement,
you could send the shuffled cards to <STDIN> for use in
a game.
<H4>Sorting an Array Using the Numeric Values</H4>
<P>
To sort an array using numeric-not string-comparisons, a subroutine
that uses the sort operator will do the comparison. The following
Perl format can be used
<BLOCKQUOTE>
<PRE>
sub bynumber { $a <=> $b }
@order = sort bynumber @chaos;
</PRE>
</BLOCKQUOTE>
<P>
where @chaos is sorted into @order.
<P>
If you wanted to take an array of jumbled numbers and sort them,
the script would look like this:
<BLOCKQUOTE>
<PRE>
sub bynumber { $a <=> $b }
@chaos = (23,4,7,456,324,3,98,45,2);
@order = sort bynumber @chaos;
</PRE>
</BLOCKQUOTE>
<P>
The numbers in @chaos are sorted into numeric order in @order.
<H4>Sorting an Array Using a Computable Field</H4>
<P>
When you have an array filled with a lot of elements that are
strings instead of numbers, it might be handy to sort them, too.
You can use a foreach loop, which is quite different from the
previous example:
<BLOCKQUOTE>
<PRE>
local(@keys);
foreach(@original_array) {
push(@keys, key_expression);
}
sub sort_function { key_comparison_expression; }
@sorted_array = @original_array[sort sort_function $[..$#original_array];
</PRE>
</BLOCKQUOTE>
<P>
where @keys hold each element's key value; @original_array is
the array to be sorted; key_expression is the expression applied
to $_ to compute a key value; sort_function is a subroutine that
signifies sorting parameters; and key_comparison_expression and
@sorted_array are the new arrays with the sorted elements.
<P>
This procedure may be used to sort user IDs in a user name file
into alphabetical order, as shown below.
<BLOCKQUOTE>
<PRE>
@user = split(/\n/, 'cat /user/ids');
local(@userkeys);
foreach(@user) {
push(@userkeys, (split(/:/))[2]);
}
sub byuserkeys { $userkeys[$x] <=> $userkeys[$y]; }
@sortuser = @user[sort byuserkeys $[..$#user];
print join("/n",@sortuser);
</PRE>
</BLOCKQUOTE>
<P>
The user IDs in /user/ids are sorted and put into @sortuser in
alphabetical order.
<H3><A NAME="ProcessingProcedures">
Processing Procedures</A></H3>
<P>
It is important to be able to modify the values in parts of your
script, and there are several problems that regularly come up.
These are dealt with as processing procedures-procedures which
modify a specified portion of the script.
<H3><A NAME="BasicProceduresinPerl">
Basic Procedures in Perl</A></H3>
<P>
These snippets of Perl code all accomplish a specific small task,
or procedure, within a Perl program, but they occur so often that
having them here for you will greatly reduce the time you spend
scripting.
<H4>Finding the Difference between Two Arrays</H4>
<P>
You may have a special page at your site that you want accessed
only once by each user, such as a quiz answer page. By comparing
two arrays-a list of registered users to your site and those who
have accessed the page already-you can eliminate those users who
have already called up the page. The script for comparing two
arrays follows.
<BLOCKQUOTE>
<PRE>
@list_of_called_users = ('user2');
@list_of_all_users = ('user1','user2','user3');
local(%check); # an associative array is setup
# to compare the two arrays
grep($check{$_}++,@list_of_called_users); # grep
# makes a list of all the entries in
# @list_of_called_users
@users_with_access = grep(!$check{$_},@list_of_all_users);
</PRE>
</BLOCKQUOTE>
<P>
where @users_with_access now contains a full list of those registered
users who can access the page. This can be used to test who can
view the page.
<H4>Finding the Intersection of Two Arrays</H4>
<P>
If you have a site that has pages you want accessed only by users
registered to two of your sites, then you can create a new list
of users for this with the format that follows.
<BLOCKQUOTE>
<PRE>
@site_one_users = ('Bob','Sue','Dan,'Doug');
@site_two_users = ('Don','Jack','Bob','Lisa');
local(%check);
grep($check{$_}++,@site_one_users);
@special_users = grep($check{$_},@site_two_users);
</PRE>
</BLOCKQUOTE>
<P>
where @special_users now contains a full list of all those users
who are registered to two of your sites, and who may now access
the special pages.
<H4>Running Block Statements for Each User</H4>
<P>
If you offer your users the ability to house their own Web pages,
you want to have a file that contains a list of all your users
with pages housed at your site. To do this you use the getpwent
and associated functions, as in the next listing.
<BLOCKQUOTE>
<PRE>
setpwent;
while (@users = getpwent) { ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) =
@user; # where all the getpwent standard
variables are listed
if (-e "$dir/index.html") { # looking for the
# standard homepage filename index.html
print "$name has a Home Page\n";
}
}
endpwent;
</PRE>
</BLOCKQUOTE>
<P>
where the users who have Web pages on your site are printed out
using their user names. You could print these names to an array,
or write them to a file, as well. <BR>
<P>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR VALIGN=TOP><TD WIDTH=576><B>NOTE</B></TD></TR>
<TR VALIGN=TOP><TD WIDTH=576>
<BLOCKQUOTE>
<I>The functions getpwent, setpwent, and endpwent all relate to each other. Their purpose is to go through a specified file to return this user information: ($name,$passwd,$iud,$gid,$quota,$comment,$gcos,$dir,$shell). Whether you have all the information
for each user is not important because any undefined variable will get the Perl undef value. Some of these variables may also have the same value on your system, such as a user's name and login ID, which are often one in the same.</I>
</BLOCKQUOTE>
</TD></TR>
</TABLE></CENTER>
<P>
<P>
An easy way to make a user's name ($name) into the user ID ($uid)
is to use this script:
<BLOCKQUOTE>
<PRE>
while (($name,$passwd,$uid) = getpwent) {
$uid{$name} = $uid;
}
</PRE>
</BLOCKQUOTE>
<H4>Interpreting a String for Variable References</H4>
<P>
You may need to be able to print the literal values of any variables
found in a string. To do this, you can use the following script
snippet:
<BLOCKQUOTE>
<PRE>
while (<STDIN>) {
s/"/\\"/g;
print eval qq/"$_"/;
</PRE>
</BLOCKQUOTE>
<P>
where the string you want expanded with literal values is already
in <STDIN>. The resulting output has the literal string
values split apart to double-quote expanded form.
<H4>Modifying All of an Array</H4>
<P>
If you want to change all of the elements of an array at the same
time, you can use grep to do it. The resulting format could look
like this:
<BLOCKQUOTE>
<PRE>
grep(OPERATION, @array_name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -