📄 perlfaq7.html
字号:
<HTML> <HEAD> <TITLE>perlfaq7</TITLE> </HEAD> <BODY background="gback.jpg"><H1>perlfaq7 - perl常问问题集,第七篇</H1><p><p><H2><A NAME="INDEX">目录</A></H2><!-- INDEX BEGIN --><UL> <LI><A HREF="#_g_W">篇名</A> <LI><A HREF="#_z">概述</A> <UL> <LI><A HREF="#_Perl_BNF_yacc_RE_">我能拿到 Perl的 BNF/yacc/RE吗?</A> <LI><A HREF="#_o_O_N_H_">$@%*这些符号是什麽意思?我怎麽知道何时该使用他们呢?</A> <LI><A HREF="#_r_r_O_">字串加引号或使用分号及逗号是否绝对必要/还是完全没必要?</A> <LI><A HREF="#_p_L_H">我如何跳过一些传回值?</A> <LI><A HREF="#_p_o_i_T_H">我如何暂时滤掉警告讯息?</A> <LI><A HREF="#_O_X_R_extension_H">什麽是一个扩充 (extension)?</A> <LI><A HREF="#_Perl_B_l_u_M_C_">为何 Perl运算子的优先顺序和 C的不一样?</A> <LI><A HREF="#_p_i_c_s">我如何宣告/生成一个资料结构 (structure)?</A> <LI><A HREF="#_p_y_X_module_H">我如何创造出一个模组 (module)?</A> <LI><A HREF="#_p_y_O_class_H">我如何创造一个类别 (class)?</A> <LI><A HREF="#_p_O_O_Q_V_F_t">我如何辨别一个变数是否被污染了(tainted)?</A> <LI><A HREF="#_closure_O_H">闭包 (closure)是啥?</A> <LI><A HREF="#_S_p_H">何谓变数自杀而我又该如何防止它?</A> <LI><A HREF="#_p_A_">我如何传递/传回一个 {函数,档案把手,阵列,杂凑阵列,方法,和正规表现式}?</A> <LI><A HREF="#_p_R_A_H">我如何生成一个静态变数?</A> <LI><A HREF="#_A_P_r_R_A_d_w_scop">动态与文字式(静态)范围界定 (scoping)有何不同? Local()和 my()呢?</A> <LI><A HREF="#_P_d_r_">当同一个范围中有一个文字式变数时,我该如何去撷取同名的动态变数?</A> <LI><A HREF="#_s_P_L_s_deep_and_sha">所谓深连结与浅连结 (deep and shallow binding)间有何不同呢?</A> <LI><A HREF="#_local_foo_FILE_L_">为何 "local($foo) = <FILE>;"无法正确地作用?</A> <LI><A HREF="#_p_s_w_q_N_B_">我如何重新定义一个内建函数、运算子或是方法?</A> <LI><A HREF="#_foo_M_foo_I_s_">用 &foo和 foo()的方式来呼叫一个函数有什麽不同?</A> <LI><A HREF="#_p_switch_case_z">我如何作一个 switch或 case叙述?</A> <LI><A HREF="#_p_I_s_w_q_">我如何抓到呼叫未定义变数/函数/方法的事件?</A> <LI><A HREF="#_b_P_">为什麽我的程式会找不到放在同一档案中的方法 (method)呢?</A> <LI><A HREF="#_p_X_e_b_package_">我如何找出目前所在的 package为何?</A> <LI><A HREF="#_p_N_j_perl_X_">我如何将一大块 perl程式码变成注解?</A> </UL> <LI><A HREF="#_P_v_y">作者与版权事宜</A></UL><!-- INDEX END --><HR><P><H1><A NAME="_g_W">篇名</A></H1>perlfaq7 - Perl语言相关问题 ($(原文版 Revision: 1.18, Date: 1997/04/24 22:44:14中译版 $Revision: 1.1 $ $Date: 1998/01/16 23:57:56 $)<P><P><HR><H1><A NAME="_z">概述</A></H1>本篇内的问题主要是不适合纳入其他篇章的一般性 Perl语言问题。<P><P><HR><H2><A NAME="_Perl_BNF_yacc_RE_">我能拿到 Perl的 BNF/yacc/RE吗?</A></H2>不行,引用 Chaim Frenkel的话:“Perl的语法无法被简化到可以用 <FONT SIZE=-1>BNF</FONT> 表示。解析Perl的工作是分散於 yacc、lexer、烟雾和镜子之间。”<P><P><HR><H2><A NAME="_o_O_N_H_">$@%*这些符号是什麽意思?我怎麽知道何时该使用他们呢?</A></H2>他们都是指定形态 (type)用的符号,如同 <A HREF="../../tppmsgs/msgs0.htm#99" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perldata.html#">perldata</A>里所详述的:<P><PRE> $纯量值 (scalar) (数字,字串或参考值 [reference]) @阵列 %杂凑阵列 (关连阵列) *代表同一个变数名的所有类形。在第四版中它们常用来达到指标 (pointers)的功能,但现在在新版的 perl中这个角色已被参考值 (reference)取代了。</PRE><P>虽然这些符号在某些场合下可省略,但建议你随处都用。<P>有些其他的符号你可能会碰到但却不是指定形态用的有:<P><PRE> <>这是用来从一个档案把手 (filehandle)里输入一份记录 \取某样东西的参考值 (reference)</PRE><P>注意 <<FONT SIZE=-1>FILE</FONT>> <EM>不是</EM>用来指定档案的形态,亦非此把手的名字。它只是 将<CODE><></CODE>这个运算子用在 <FONT SIZE=-1>FILE</FONT>这个把手上。在纯量的情境 (scalar context) 下,它自 <FONT SIZE=-1>FILE</FONT> 把手一次读入一行 (嗯,该说一笔记录,参看 <A HREF="../../tppmsgs/msgs1.htm#100" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perlvar.html#_">$/</A>),在序列情境 (list context)下,则一次将 <EM>全部</EM>的内容读 入。当对档案使用开、关或其它 <CODE><></CODE>之外的动作、或甚至只是提到把 手时,切记<EM>不要</EM>使用 <CODE><></CODE>。下面的用法是正确的:<CODE>eof(FH)</CODE>,<CODE>seek(FH, 0,2)</CODE>以及 ``copying from <FONT SIZE=-1>STDIN</FONT> to FILE''。<P><P><HR><H2><A NAME="_r_r_O_">字串加引号或使用分号及逗号是否绝对必要/还是完全没必要?</A></H2>通常一个没有冠上形态符号的字 (bareword)是不需被纳入引号里的,但在大多数的情况下或许该这麽做 (在<CODE>use strict</CODE>下则是必须的)。但由一个简单的字(不能是一个已定义的副函数之名称)所构成的索引值,和 <CODE>=></CODE>左端的运算子,都会被视为已纳入引号了:<P><PRE>这些是和这些一样的 ------------ --------------- $foo{line} $foo{"line"} bar => stuff "bar" => stuff</PRE><P>一个区块末端的分号可有可无,一个序列的最後一个逗号亦同。良好的写作风格(参看<A HREF="../../tppmsgs/msgs0.htm#79" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perlstyle.html#">perlstyle</A>)中建议除了在单行程式 (one-liners)的情况外都将他们加上去:<P><PRE> if ($whoops) { exit 1 } @nums = (1, 2, 3);</PRE><P><PRE> if ($whoops) { exit 1; } @lines = ( "There Beren came from mountains cold", "And lost he wandered under leaves", );</PRE><P><P><HR><H2><A NAME="_p_L_H">我如何跳过一些传回值?</A></H2>一种方法是将传回值当作序列来对待,然後用索引来指名其中的某个位置:<P><PRE> $dir = (getpwnam($user))[7];</PRE><P>另一种方法就是在等号左端用 undef 作元素:<P><PRE> ($dev, $ino, undef, undef, $uid, $gid) = stat($file);</PRE><P><P><HR><H2><A NAME="_p_o_i_T_H">我如何暂时滤掉警告讯息?</A></H2><CODE>$^W</CODE>变数 (在 <A HREF="../../tppmsgs/msgs1.htm#100" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perlvar.html#">perlvar</A>中有说明)控制一个区块在执行期 (runtime)的警告讯息:<P><PRE> { local $^W = 0; #暂时关掉警告讯息 $a = $b + $c; #我知道这些变数可能未定义 }</PRE><P>注意,像所有的标点符号变数一样,目前不能对 <CODE>$^W</CODE>用 my,只能用 <CODE>local()。</CODE><P>一个发展中的新 <CODE>use warnings</CODE>编译器指挥模组 (pragma) 提供了更精细的控制。好奇宝宝们应该翻翻 perl5-porters邮件论坛的档案库以获得更详细的说明。<P><P><HR><H2><A NAME="_O_X_R_extension_H">什麽是一个扩充 (extension)?</A></H2>一种从 Perl呼叫编译好的 <FONT SIZE=-1>C</FONT>程式码的方法。阅读 <A HREF="../../tppmsgs/msgs0.htm#71" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perlxstut.html#">perlxstut</A>是个多了解扩充(extensions)的好方法。<P><P><HR><H2><A NAME="_Perl_B_l_u_M_C_">为何 Perl运算子的优先顺序和 C的不一样?</A></H2>事实上它们是相同的。所有 Perl自 <FONT SIZE=-1>C</FONT>借过来的运算子都具备与原来在 <FONT SIZE=-1>C</FONT> 中相同的优先顺序。问题出在那些 <FONT SIZE=-1>C</FONT>没有的运算子,特别是那些将其右方一律当成序列情境对待的函数,例如 print, chmod, exec等等。这类的函数被称作“序列运算子”(list operators),在 <A HREF="../../tppmsgs/msgs0.htm#69" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perlop.html#">perlop</A>的优先顺序表中就是这麽称呼。<P>一个常犯的错误像是:<P><PRE> unlink $file || die "snafu";</PRE><P>这会被解译器看成是:<P><PRE> unlink ($file || die "snafu");</PRE><P>要避免此问题,须加上括号或是用超低优先的 <CODE>or</CODE>运算子:<P><PRE> (unlink $file) || die "snafu"; unlink $file or die "snafu";</PRE><P>这些“英文的”运算子 (<CODE>and</CODE>, <CODE>or</CODE>, <CODE>xor</CODE>,及 <CODE>not</CODE>)是刻意设计成较一般序列运算子低的优先顺序,这就是为了解决前述的状况。<P>另一个拥有出人意料的优先顺序者为指数。它甚至高於负号,这使得 <CODE>-2**2</CODE>变成负四而非正四。他同时也会“向右靠”(right-associate),意思是说 <CODE>2**3**2</CODE> 代表二的九次方,而不是八的平方。<P><P><HR><H2><A NAME="_p_i_c_s">我如何宣告/生成一个资料结构 (structure)?</A></H2>一般来说,我们不 ``宣告''一个结构。用一个 (通常是匿名的) 杂凑阵列的参考值 (hash reference)即可。参看 <A HREF="../../tppmsgs/msgs0.htm#59" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perlref.html#">perlref</A> 以及 <A HREF="../../tppmsgs/msgs0.htm#64" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perldsc.html#">perldsc</A>,里面有更多资料。以下是一个范例:<P><PRE> $person = {}; #新的不具名杂凑阵列 $person->{AGE} = 24; #把 AGE栏的值设成 24 $person->{NAME} = "Nat"; #将 NAME栏设成 "Nat"</PRE><P>如果你要的是更严谨的写法,看看 <A HREF="../../tppmsgs/msgs0.htm#57" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perltoot.html#">perltoot</A>。<P><P><HR><H2><A NAME="_p_y_X_module_H">我如何创造出一个模组 (module)?</A></H2>一个模组就是一个放在同名档案里的包裹(package)。例如,Hello::There模组会放在Hello/There.pm。<A HREF="../../tppmsgs/msgs0.htm#60" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perlmod.html#">perlmod</A> 里有详尽说明。<A HREF="../../tppmsgs/msgs1.htm#101" tppabs="http://www.perl.org/CPAN/doc/manual/html/lib/Exporter.html#">Exporter</A> 也会很有帮助。如果你正在写一个 <FONT SIZE=-1>C</FONT> 或是混合了 <FONT SIZE=-1>C</FONT>及 Perl 的模组,那麽你就该读 <A HREF="../../tppmsgs/msgs0.htm#71" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perlxstut.html#">perlxstut</A>。<P>下面是个方便的样板,你也许希望在撰写第一个模组时将他派上用场。记得要改名字。<P><PRE> package Some::Module; #假设是 Some/Module.pm</PRE><P><PRE> use strict;</PRE><P><PRE> BEGIN { use Exporter (); use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);</PRE><P><PRE> ##设定版本以备版本检查之用;去掉 "#"号即可使用。 ## $VERSION = 1.00;</PRE><P><PRE> #如果有使用 RCS/CVS,那应该考虑将下一行保留, #但是小心两位数版本编号可能造成的影响。 $VERSION = do{my@r=q$Revision: 1.1 $=~/\d+/g;sprintf '%d.'.'%02d'x$#r,@r};</PRE><P><PRE> @ISA = qw(Exporter); @EXPORT = qw(&func1 &func2 &func3); %EXPORT_TAGS = ( ); #例如: TAG => [ qw!name1 name2! ],</PRE><P><PRE> #整个包裹要输出的全域变数(exported package globals)在此, #还有其他选择要输出的函数。 @EXPORT_OK = qw($Var1 %Hashit); } use vars @EXPORT_OK;</PRE><P><PRE> #没有输出的全域变数在此。 use vars qw( @more $stuff );</PRE><P><PRE> #起始包裹内的全域变数,首先是要输出的那几个。 $Var1 = ''; %Hashit = ();</PRE><P><PRE> #接下来是其他的 (还是能以 $Some::Module::stuff的方式撷取他们的值) $stuff = ''; @more = ();</PRE><P><PRE> #所有以档案为范围的变数名都 #必须在让後面的函数使用前先创造出来。</PRE><P><PRE> #以档案为范围的变数名在此。 my $priv_var = ''; my %secret_hash = ();</PRE><P><PRE> #下面是一个以档案为限的函数,当作一个闭包 #可以用 &$priv_func的方式呼叫它;但不能使用原型定义 my $priv_func = sub { #程式码放在这里 };</PRE><P><PRE> #不论是否要输出,都记得要将你的函数造出来。 #别忘了在 {}括号间放些有趣的内容。</PRE><P><PRE> sub func1 {} #没有定义原型 sub func2() {} #定原型为 void sub func3($$) {} #定原型为两个纯量值
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -