⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch3.htm

📁 美国Macmillan出版社编写的Perl教程《Perl CGI Web Pages for WINNT》
💻 HTM
📖 第 1 页 / 共 4 页
字号:
</BLOCKQUOTE>

<P>

in no particular order.

<H4>The Each Operator</H4>

<P>

To inspect all the elements of an associative array, you can use

the each operator like the other

<BLOCKQUOTE>

<PRE>

each(%wolf);

</PRE>

</BLOCKQUOTE>

<P>

which would return the first key/value pair in the array:

<BLOCKQUOTE>

<PRE>

% 4,moon,5,howl,6,six

</PRE>

</BLOCKQUOTE>

<H4>The Delete Operator</H4>

<P>

This is the operator which allows you to remove key-value pairs

by designating the key of the pair you want removed:

<BLOCKQUOTE>

<PRE>

%wolf = (4,&quot;four&quot;,5,&quot;five&quot;,6,&quot;six&quot;);

delete $wolf{5};

# returns an element list for

# %wolf of (4,&quot;four&quot;,6,&quot;six&quot;)

</PRE>

</BLOCKQUOTE>

<H3><A NAME="IO">

I/O</A></H3>

<P>

We already know that you can use &lt;STDIN&gt; to take a line

of user input and store it as a scalar variable value. We also

know that you can put a collection of user input from &lt;STDIN&gt;

into an array, where each line entered is kept as a separate element

in the array key/value pairs. But we haven't yet really focused

on how to manipulate these values.

<P>

Perhaps you want to go through each line of text and change some

of them. You might do this by creating a simple loop, like this

one:

<BLOCKQUOTE>

<PRE>

while ($_ = &lt;STDIN&gt;) {

}

</PRE>

</BLOCKQUOTE>

<P>

where the command while creates a repetition loop. Perl will keep

putting the lines in &lt;STDIN&gt; into the scalar variable $_

until the file runs out of lines and the loop dies. 

<P>

When using Perl output, both the familiar print and related printf

operators can be used to write to &lt;STDOUT&gt;. The print operator

can do more than just produce text to display; this operator acts

like a list operator and can move strings into &lt;STNOUT&gt;

without adding any characters.

<P>

The printf operator gives you more command over your strings than

print does. With printf you can designate a format control string

with the first argument, which will determine how the rest of

the arguments will be printed. An example might be:

<BLOCKQUOTE>

<PRE>

printf &quot;%1&Oslash; %2&Oslash;&quot;, $wolf, $moon;

</PRE>

</BLOCKQUOTE>

<P>

where $wolf will be printed to a 10-character field and $moon

will be printed to a 20-character field.

<P>

There are other modifiers that can be used with the printf operator

that can designate the string to be printed as a decimal integer,

floating-point value, or with spaces or tabs.

<H3><A NAME="UsingaRegularExpression">

Using a Regular Expression</A></H3>

<P>

To demonstrate a simple use of a regular expression, I want to

introduce you to a simple command called grep, short for global

regular expression print. Grep is a very powerful command that

has come from the UNIX world. With grep you can take a regular

expression and search a file line by line, trying to match the

string indicated in the regular expression. Using grep at the

command line might look like this:

<BLOCKQUOTE>

<PRE>

grep crypt bonus.pl

% bonus_change.pl

</PRE>

</BLOCKQUOTE>

<P>

where grep will examine every line of code in bonus.pl to see

if it contains the string &quot;crypt,&quot; and then output those

lines into the file bonus_change.pl via &lt;STDOUT&gt;.

<P>

To denote the string &quot;crypt&quot; as a regular expression

in Perl, it is enclosed between slashes like

<BLOCKQUOTE>

<PRE>

/crypt/

</PRE>

</BLOCKQUOTE>

<P>

and would look like this in a script:

<BLOCKQUOTE>

<PRE>

if (/crypt/) {

print &quot;$_&quot;;

}

</PRE>

</BLOCKQUOTE>

<P>

where the regular expression crypt is tested against the special

variable $_, the default scalar variable where everything has

been stored at one time or another.

<P>

There are a number of special variables in Perl, like $_, that

have their own designated features designed to make Perl easier

to use, and they are touched on throughout the book where most

appropriate.

<H3><A NAME="TheGuestbook">

The Guestbook</A></H3>

<P>

Let's start with a simple example of a guestbook using WinPerl.

First you'll want to create a Perl file called guest.pl.<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>You can write Perl scripts in any text processing application, like Notepad, Write, or Microsoft Word, if you so desire. Whatever you use to create your scripts, remember to save your script as text only, and with the .pl file extension. </I>

</BLOCKQUOTE>



</TD></TR>

</TABLE></CENTER>

<P>

<P>

In keeping with good programming practice, the first line of the

script will be a comment line stating the name of the file. This

is very handy when you, or someone else, may have to work with

the file later on. The script looks like this:

<BLOCKQUOTE>

<PRE>

#! usr/bin/perl

# guest.pl

print &quot;What is your Name? &quot;;

$name=&lt;STDIN&gt;; # get the response

# from the user

open (GUESTBOOK, &quot;&gt;&gt;guest.pl&quot;);

# open a file with

# filehandle GUESTBOOK

print GUESTBOOK &quot;$name&quot;; # append

# the name to the guestbook file

chop($name); # remove the newline

print &quot;Thank you, $name! Your name has been added to the Guestbook.\n&quot;;

close(GUESTBOOK);

</PRE>

</BLOCKQUOTE>

<P>

So, what's going on here? We first print the prompt for the user.

The&nbsp;print command will default to &lt;STDOUT&gt;, in this

case, the screen.

<P>

We then use the &lt;&gt; construct to retrieve a line from a filehandle,

&lt;STDIN&gt;, which is the keyboard input up to a newline. We

next open a file called guest.pl, which is assigned a filehandle

of GUESTBOOK. The filehandle is used to reference the opened file

for reading or writing and it is usually all capitals. This filehandle,

like all variables or arrays in Perl, can be just about anything

you like, as long as it isn't a reserved word. You might notice

that we put &gt;&gt; in front of the filename. This means we are

opening the file for appending. The options for file opening are

in Table 3.1.<BR>

<P>

<CENTER><B>Table 3.1 File Opening Options</B></CENTER>

<P>

<CENTER>

<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=40% CELLPADDING=3>

<TR VALIGN=TOP><TD><CENTER><B>Operator</B></CENTER></TD><TD><B>Action</B>

</TD></TR>

<TR VALIGN=TOP><TD><CENTER>&gt; </CENTER></TD><TD>Write

</TD></TR>

<TR VALIGN=TOP><TD><CENTER>&gt;&gt;</CENTER></TD><TD>Append

</TD></TR>

<TR VALIGN=TOP><TD><CENTER>+&gt;</CENTER></TD><TD>Read and Write

</TD></TR>

<TR VALIGN=TOP><TD><CENTER>Nothing</CENTER></TD><TD>Read

</TD></TR>

</TABLE></CENTER>

<P>

<P>

Once the file is open, and we have a filehandle, we can put the

name into the guestbook file with a print command. Notice that

we do this by putting the filehandle directly after the print

statement. In fact, the normal print &quot;string&quot; command

is actually a short version of

<BLOCKQUOTE>

<PRE>

print &lt;STDOUT&gt; &quot;string&quot;;

</PRE>

</BLOCKQUOTE>

<P>

We print the next line to the screen. We have put the variable

$name inside the string, and it will be printed as we entered

it. This is called variable interpolation; the variable is replaced

in the string before it is printed.

<P>

The chop() command called before the print removes the last character

in the string $name. This is used to remove the newline that is

appended to the string when it is entered from the keyboard. If

we didn't do this, we would end up with an extra newline printed

right after the name, and the exclamation point on a line by itself.

Not such a good idea, grammatically speaking. We left the newline

on when we printed it to the file because we wanted each name

on its own line.

<P>

Finally, we close the file and end the program. We don't actually

need to close the file, as Perl will close it automatically if

it is reopened or the program ends, but it is good programming

practice to put it there.

<P>

Okay, so now we have a database full of the names of our guests.

What next?

<P>

Well, the next logical step would be to check the file to see

if you have already visited so the database isn't filled up with

repeat customers. The procedure shown in Listing 3.1 shows you

how.

<HR>

<BLOCKQUOTE>

<B>Listing 3.1 Checking the Database for Repeat Visitors<BR>

</B>

</BLOCKQUOTE>

<BLOCKQUOTE>

<PRE>

Checking the file chop($name); # remove the newline

print &quot;Thank you, $name! Your name has been added to the Guestbook.\n&quot;;

close(GUESTBOOK);

print &quot;What is your Name?&quot;;

$name=&lt;STDIN&gt;; # get the response

# from the user

open (GUESTBOOK, &quot;guest.pl&quot;);

# open a file with filehandle

# GUESTBOOK

while ($line=&lt;GUESTBOOK&gt;) {

        if ($line eq $name) {

                print &quot;Your name is already in the guestbook!\n&quot;;

                close(GUESTBOOK);

              exit;

     }

}

close (GUESTBOOK); # close file

# for read

open (GUESTBOOK, &quot;&gt;&gt;guest.pl&quot;);

# open same file for append

print GUESTBOOK &quot;$name&quot;; # append

# the name to the guestbook file

chop($name); # remove the newline

print &quot;Thank you, $name! Your name has been added to the Guestbook.\n&quot;;

close(GUESTBOOK);

</PRE>

</BLOCKQUOTE>

<HR>

<P>

Let's have a look at the new part. The while loop will continue

until the condition is false. The condition in this case is assigning

the variable $line to each line of GUESTBOOK, terminated with

a newline.

<P>

This is the procedure we did when we got the name of the guest,

except we are now obtaining it from a file rather than &lt;STDIN&gt;.

This condition will continue to be true until there are no more

lines in the file. Notice that we opened the file guest.pl with

a read, so we can get the lines.

<P>

The if condition compares each $line with $name. We use the operator

eq here because the variables are strings. If they were numbers,

we would use a different set of comparison operators. Because

Perl makes no distinction between string variables and numeric

variables, we must be cautious as to which comparison operators

we use. Perl will compare &quot;5&quot; and &quot;10&quot; differently

depending on whether you use a string or numeric operator. &quot;5&quot;

will be less than &quot;10&quot; in a numeric sense, but greater

than &quot;10&quot; in a string context. Table 3.2 lists the possible

operators in both string and numeric context.<BR>

<P>

<CENTER><B>Table 3.2 Numeric versus String Operators</B></CENTER>

<P>

<CENTER>

<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=65% CELLPADDING=3>

<TR VALIGN=TOP><TD><CENTER><B>Numeric Operator</B></CENTER></TD>

<TD><CENTER><B>String Operator</B></CENTER></TD><TD><B>Definition</B>

</TD></TR>

<TR VALIGN=TOP><TD><CENTER>==</CENTER></TD><TD><CENTER>eq</CENTER>

</TD><TD>Equal to</TD></TR>

<TR VALIGN=TOP><TD><CENTER>!=</CENTER></TD><TD><CENTER>ne</CENTER>

</TD><TD>Not equal to</TD></TR>

<TR VALIGN=TOP><TD><CENTER>&gt;</CENTER></TD><TD><CENTER>gt</CENTER>

</TD><TD>Greater than</TD></TR>

<TR VALIGN=TOP><TD><CENTER>&gt;=</CENTER></TD><TD><CENTER>ge</CENTER>

</TD><TD>Greater than or equal to</TD></TR>

<TR VALIGN=TOP><TD><CENTER>&lt;</CENTER></TD><TD><CENTER>lt</CENTER>

</TD><TD>Less than</TD></TR>

<TR VALIGN=TOP><TD><CENTER>&lt;=</CENTER></TD><TD><CENTER>le</CENTER>

</TD><TD>Less than or equal to</TD></TR>

<TR VALIGN=TOP><TD><CENTER>&lt;=&gt;</CENTER></TD><TD><CENTER>cmp</CENTER>

</TD><TD>Not equal to, with numeric return</TD></TR>

</TABLE></CENTER>

<P>

<P>

A quick note on the compare operator: It will return a -1 if it

is less than, and a +1 if it is greater than.

<P>

The exit command within the if body will stop the program after

informing the user that his or her name is already in the guestbook.

We could have acomplished the same thing in one line with the

die command:

<BLOCKQUOTE>

<PRE>

if ($line eq $name) {

        die &quot;Your name is already in the guestbook!\n&quot;;

}

</PRE>

</BLOCKQUOTE>

<P>

This is useful for command line programs, but does not work very

well with CGI scripts, so it isn't used very often.

<P>

If the name isn't found in the GUESTBOOK file, we exit the while

loop, and continue on with the program. We have to close the file

and reopen it in append mode so that we can add the name to the

end of the file. Once again, strictly speaking, we don't have

to close the file before reopening it, but it is good practice

so that we develop a sense of what is happening, and when, in

our scripts. When dealing with larger programs it can get a little

confusing as to what is happening at a particular point in the

code.

<P>

Although we used ($line eq $name) in the above example, this is

not necessarily the best way to test equivalency. In this case,

the two strings must be <I>exactly</I> equal, which means &quot;john&quot;

and &quot;John&quot; are not equal. Also, if there happens to

be a newline in one string and not the other, then Perl will call

them differently. To get around some of these nuisances, we use

something called a regular expression.

<P>

Regular expressions in Perl come in very handy, as they are much

less cumbersome to use and a lot more flexible then string searching

and comparison in some other languages (which will remain nameless).

Let's look at an equivalent expression to the one used above:

<BLOCKQUOTE>

<PRE>

if ($line =~ /john/) {

# do some stuff...

}

</PRE>

</BLOCKQUOTE>

<P>

There are a few things going on here. First, we are using a new

operator.

<P>

The =~ operator is the regular expression operator. We will use

it a lot to&nbsp;do all types of searching and replacing. Here

we use it to compare $line with the expression between the /'s.

If the variable $line contains the string&nbsp;&quot;john,&quot;

then the condition is true. This means that the strings will match

if $line is equal to &quot;john,&quot; &quot;johnathan,&quot;

&quot;joe johnston,&quot; or &quot;john and&nbsp;the beanstalk.&quot;

<P>

If we want to be sure that the first name begins with &quot;john,&quot;

we can change the expression slightly to yield

<BLOCKQUOTE>

<PRE>

if ($line =~/^john/) {

</PRE>

</BLOCKQUOTE>

<P>

The ^ character tells Perl that the variable $line must <I>start</I>

with &quot;john&quot; in order to match. This will match &quot;john,&quot;

&quot;johnny,&quot; and &quot;john smith&quot; but not &quot;big

john&quot; or &quot;joe johnston.&quot;

<P>

Ok, so what about case? The current expression doesn't do uppercase,

so &quot;john&quot; will match, but &quot;John&quot; will not.

Another simple change:

<BLOCKQUOTE>

<PRE>

if ($line =~/^john/i) {

</PRE>

</BLOCKQUOTE>

<P>

The &quot;i&quot; after the last / tells Perl to ignore the case

of the regular expression so that we now will match &quot;John,&quot;

&quot;Johnathan,&quot; and &quot;JOHN.&quot;

<P>

Of course, we don't want to match $line to just John, we want

to match it to the user input in the variable $name. Well, remember

variable interpolation, where a variable name in a string gets

substituted for its value before the string gets printed? The

same thing applies in regular expressions:

<BLOCKQUOTE>

<PRE>

if ($line =~/^$name/i) {

</PRE>

</BLOCKQUOTE>

<P>

Now the condition is true if $line is a string beginning with

$name in any combination of upper- and lowercase. Amazing!

<P>

A note on regular expressions: Some of the characters in a regular

expression are significant (like the ^) and will not become part

of the expression itself.

<P>

If you want to match these characters, you must &quot;escape&quot;

them. For instance, if you wanted to match the variable $line

to &quot;caret^,&quot; you would precede the ^ by backslash in

the regular expression

<BLOCKQUOTE>

<PRE>

if ($line =~/caret\^/) {

</PRE>

</BLOCKQUOTE>

<P>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -