📄 ch4.htm
字号:
&hey_now($a); # to create Hey, now! Here's Hank!
</PRE>
</BLOCKQUOTE>
<P>
or
<BLOCKQUOTE>
<PRE>
&hey_now("Artie")+&hey_now("Bob"); # to create
# Hey, now! Here's Artie! Hey, now! Here's Bob!
</PRE>
</BLOCKQUOTE>
<P>
If you want to use more than one parameter in the @_ array, then
you might write a script like this:
<BLOCKQUOTE>
<PRE>
sub hey_now {
print "$_[0], $_[1]!\n";
}
&hey_now("Hey,"," now!"); # which would print
# Hey, now!
</PRE>
</BLOCKQUOTE>
<P>
where only those parameters defined in the script are examined.
<P>
Using the @_ variable is different because it is local to the
subroutine, unlike previous cases where other variables were global
to the entire script. A global value can be given to @_, but it
has to be done before the subroutine is invoked, and then restored
after the subroutine is completed. One result of this local variable
feature is that a subroutine can pass arguments to another subroutine
without the hassle of having to restate the value in the first
subroutine. Each subroutine keeps its own @_ variable.
<P>
If we update a previous example, we can add the @_ variable:
<BLOCKQUOTE>
<PRE>
sub two_variables {$_[Ø] + $_[1];
{
print &two_variables(1Ø,1); # which prints 11
$S = two_variables(1,2); # which gives $S the
value of 3
</PRE>
</BLOCKQUOTE>
<P>
You can expand this example to manipulate many values at a time,
like so:
<BLOCKQUOTE>
<PRE>
sub plus {
$add = Ø; # start of the addition
foreach $_ (@_) {
$add += $_; # add each new element
}
$add; # the expression evaluated outside the
nested argument
}
$P = &plus(1,2,3,4); # gives $P the value of 10
print &plus(6,3,5,2); # prints 16
print &plus(1..4); # prints 1Ø
</PRE>
</BLOCKQUOTE>
<P>
If we were already using a variable named $plus somewhere else
in the script, we might encounter a problem because after this
subroutine the value for $plus is completely changed. You can
avoid accidently "stepping on" variable values by understanding
how local variables work with user functions.
<H3><A NAME="UserFunctionsandLocalVariables">
User Functions and Local Variables</A></H3>
<P>
Just like the special @_ variable discussed with user functions,
those that have the ability to have a value locally (scalars,
arrays, and associative arrays) can work this way, too.
<P>
Perl provides the operator local() to designate, or instantiate,
local versions of the variable in question. Using local() might
look like
<BLOCKQUOTE>
<PRE>
sub plus {
local($add); # makes $add a local variable
$add = Ø; # starts the value
foreach $_ (@_) {
$add += $_; # add each element together
}
$add; # the total
}
</PRE>
</BLOCKQUOTE>
<P>
where at the beginning of the subroutine the current value of
the global variable $add is stored away, and a brand new variable
$add is created. This variable starts out with the value undef.
Once the subroutine finishes, the local variable $add dies, and
the global variable $add is restored, with its global value intact.
<BR>
<P>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR VALIGN=TOP><TD WIDTH=576><B>WARNING!</B></TD></TR>
<TR VALIGN=TOP><TD WIDTH=576>
<BLOCKQUOTE>
<I>The local () operator is a full, executable operator, and can wreak havoc on your variable values if not used carefully. Good Perl etiquette suggests that you place all your local() operators at the start of your subroutine definitions. </I>
</BLOCKQUOTE>
</TD></TR>
</TABLE></CENTER>
<P>
<P>
You can also use the local() operator on an assignable array list,
which means you can use it like this:
<BLOCKQUOTE>
<PRE>
local($P, @q) = @_;
</PRE>
</BLOCKQUOTE>
<P>
or as the left side to an array assignment operator. The scalar
$P is added to the array @q and held locally in the default array
@_. This array list only has value locally in a block statement
or subroutine.
<H3><A NAME="MoreControlStructures">
More Control Structures</A></H3>
<P>
There are a few more Perl operators that act as control structures
that you should know about. They work very well with subroutines,
and other self-contained Perl script structures, like loops and
block statements. These operators are last, next, and redo, and
they, like the other operators, work both in and out of subroutines,
modifying the action of the subroutine, or block statement.
<P>
The main difference between a subroutine and a block statement
is that the subroutine, once defined, can be called into action
in a script by simply prefacing the subroutine name with the command
Sub. A block statement, being a self-contained function in a script
(like a while loop or array definition), only performs its action
where it is placed in the script, and must be written out in whole
again, if you want to repeat its action. To avoid unnecessary
scripting, subroutines are very popular in Perl.
<H4>The Last Operator</H4>
<P>
There may be a time when you need to get out of a loop before
it has completed all of its cycles. You can use the last operator
to do this. It will cause the loop to stop, and the first statement
following the loop statement block will stop also. A format for
using the last operator might look like this:
<BLOCKQUOTE>
<PRE>
while (a_condition) {
statement1;
statement2;
statement3;
if (another_condition) {
statement4;
statement5;
statement6;
last;
}
statement7;
statement8;
statement9;
}
# last goes here to break the loop
</PRE>
</BLOCKQUOTE>
<P>
where if a_condition in the loop is true, then statements 1, 2,
and 3 are executed, and then ifanother_condition is true, then
statements 4, 5, and 6 are executed, and then the last operator
breaks into the loop and takes you to the end of the entire loop
statement block.
<P>
The last operator works only on those statement blocks of the
for, foreach, while, and naked kind. Naked blocks are those that
belong to no other script construct.
<P>
To demonstrate a more practical use of the last operator, we can
apply it to searching through an e-mail header. The header might
look like this:
<BLOCKQUOTE>
<PRE>
From: jhagey@sentex.net (Jonathan Hagey)
To: reader@my_server.com
Date: 12-MAY-96 05:23:14 AM EST -0600
Subject: Good luck!
</PRE>
</BLOCKQUOTE>
<P>
Writing good scripts takes practice, patience, and a good manual!
<P>
If you wanted to have a script scan through the e-mail to check
and see if it went to the right person, and that there were no
spelling mistakes in the recipient's e-mail address, you might
try this:
<BLOCKQUOTE>
<PRE>
while (<STDIN>) {
if (/^To:/) { # check to see if it starts
# with To:
if (/reader/) { # correct name
print "It's going to the right person.\n";
}
last; # have found To:, so exit
} # end of if To: loop
if (/^$/) { # in case of a blank line
last; # when blank line, stop checking
}
} # end of while loop
</PRE>
</BLOCKQUOTE>
<P>
This loop could be adapted to take a variable that held any recipient's
name, to give the script more flexibility. The variable, possibly
the default $_, would replace the static "reader" in
the regular expression and then this variable would use <STDIN>
to read the person's name from your input.
<H4>The Next Operator</H4>
<P>
This operator is used inside a loop, and when it is used it causes
the execution to jump ahead to the next statement block, without
killing the one it occupies.
<P>
The typical format for the next operator is this:
<BLOCKQUOTE>
<PRE>
while (a_condition) {
start_of_block1;
block1;
end_of_block2;
if (next_condition) {
start_of_block2;
block2;
end_of_block2;
next; # skips next block
}
start_of_block3;
block3;
end_of_block3;
# this is where next goes to
}
</PRE>
</BLOCKQUOTE>
<P>
You might need this function to avoid running unnecessary checks-
which take up valuable online time-on users who have already established
themselves as members of your site, and don't need page after
page of security scrutiny, or have already defined their tastes
as far as sections of your site go, so they are directly moved
by the script to that location.
<H4>The Redo Operator</H4>
<P>
This operator works like the Next operator, only in reverse. If
you need a loop to go back and run through a portion of script
again, you can use the Redo operator. The format is similar:
<BLOCKQUOTE>
<PRE>
while (a_condition) {
# redo returns here
start_of_block1;
block1;
end_of_block1;
if (next_condition) {
start_of_block2;
block2;
end_of_block2;
redo; # goes back up to the marked block
}
start_of_block3;
block3;
end_of_block3;
}
</PRE>
</BLOCKQUOTE>
<P>
It's as straightforward as that.
<H4>Labeling Blocks</H4>
<P>
When dealing with statement blocks in Perl you can use the last,
next, and redo operators to move around your script with great
flexibility. If you wanted to get out of two nested blocks at
the same time, you can use a label with the block statements.
Labeling is a programming method very similar to subroutines,
because once you define the action of the label, you can apply
it as many times as you need to the actions in your script. Labeling
is not as extensive as a subroutine though, as it is only able
to define a specific function, like a particular loop condition.
<P>
Statement blocks are labeled when you give them a name, following
this format:
<BLOCKQUOTE>
<PRE>
LABELNAME: loop_operator(condition) {
statement1;
statement2;
if(another_condition) {
block_modifier LABELNAME;
}}
</PRE>
</BLOCKQUOTE>
<P>
where the label's name is always in uppercase letters to prevent
confusing it with scalars, arrays, associative arrays, reserved
words, and user functions.
<P>
A typical use for a labeled block might be similar to the following,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -