📄 ch02_11.htm
字号:
</blockquote>except that it isn't so cumbersome to say, and will actually work.It really does shift array <tt class="literal">@ARGV</tt> and put the current filenameinto the global variable <tt class="literal">$ARGV</tt>. It also uses the specialfilehandle <tt class="literal">ARGV</tt> internally--<tt class="literal"><></tt>is just a synonym forthe more explicitly written <tt class="literal"><ARGV></tt>, which is a magicalfilehandle. (The pseudocode above doesn't work because it treats<tt class="literal"><ARGV></tt> as nonmagical.)</p><p>You can modify <tt class="literal">@ARGV</tt> before the first<tt class="literal"><></tt> as long as the array ends up containingthe list of filenames you really want. Because Perl uses its normal<tt class="literal">open</tt> function here, a filename of"<tt class="literal">-</tt>" counts as standard input wherever it isencountered, and the more esoteric features of <tt class="literal">open</tt>are automatically available to you (such as opening a "file" named"<tt class="literal">gzip -dc < file.gz|</tt>"). Line numbers(<tt class="literal">$.</tt>) continue as if the input were one big happyfile. (But see the example under <tt class="literal">eof</tt> in<a href="ch29_01.htm">Chapter 29, "Functions"</a> for how toreset line numbers on each file.)</p><p>If you want to set <tt class="literal">@ARGV</tt> to your own list of files, go right ahead:<blockquote><pre class="programlisting"># default to README file if no args given@ARGV = ("README") unless @ARGV;</pre></blockquote>If you want to pass switches into your script, you can use one of the<tt class="literal">Getopt::*</tt> modules or put a loop on the front like this:<blockquote><pre class="programlisting">while (@ARGV and $ARGV[0] =~ /^-/) { $_ = shift; last if /^--$/; if (/^-D(.*)/) { $debug = $1 } if (/^-v/) { $verbose++ } ... # other switches}while (<>) { ... # code for each line}</pre></blockquote>The <tt class="literal"><></tt> symbol will return false only once. If you call itagain after this, it will assume you are processing another <tt class="literal">@ARGV</tt>list, and if you haven't set <tt class="literal">@ARGV</tt>, it will input from <tt class="literal">STDIN</tt>.</p><p><a name="INDEX-754"></a>If the string inside the angle brackets is a scalar variable (forexample, <tt class="literal"><$foo></tt>), that variable contains an <em class="emphasis">indirect</em>filehandle, either the name of the filehandle to input from or areference to such a filehandle. For example:<blockquote><pre class="programlisting">$fh = \*STDIN;$line = <$fh>;</pre></blockquote>or:<blockquote><pre class="programlisting">open($fh, "<data.txt");$line = <$fh>;</pre></blockquote></p><h3 class="sect2">2.11.3. Filename Globbing Operator</h3><a name="INDEX-755"></a><a name="INDEX-756"></a><a name="INDEX-757"></a><a name="INDEX-758"></a><a name="INDEX-759"></a><a name="INDEX-760"></a><p>You might wonder what happens to a line input operator if you putsomething fancier inside the angle brackets. What happens is that itmutates into a different operator. If the string inside the anglebrackets is anything other than a filehandle name or a scalar variable(even if there are just extra spaces), it is interpreted as a filenamepattern to be "globbed".<a href="#FOOTNOTE-19">[19]</a> The pattern is matched against the files in thecurrent directory (or the directory specified as part of the fileglobpattern), and the filenames so matched are returned by the operator. Aswith line input, names are returned one at a time in scalar context,or all at once in list context. The latter usage is morecommon; you often see things like:<blockquote><pre class="programlisting">@files = <*.xml>;</pre></blockquote>As with other kinds of pseudoliterals, one level of variableinterpolation is done first, but you can't say <tt class="literal"><$foo></tt> becausethat's an indirect filehandle as explained earlier. In older versions ofPerl, programmers would insert braces to force interpretation as afileglob: <tt class="literal"><${foo}></tt>. These days, it's considered cleanerto call the internal function directly as <tt class="literal">glob($foo)</tt>, which isprobably the right way to have invented it in the first place.So instead you'd write<blockquote><pre class="programlisting">@files = glob("*.xml");</pre></blockquote>if you despise overloading the angle operator for this.Which you're allowed to do.</p><blockquote class="footnote"><a name="FOOTNOTE-19"></a><p>[19]Fileglobs have nothing to do with thepreviously mentioned typeglobs, other than that they both use the <tt class="literal">*</tt>character in a wildcard fashion. The <tt class="literal">*</tt> character has the nickname"glob" when used like this. With typeglobs, you're globbing symbols withthe same name from the symbol table. With a fileglob, you're doingwildcard matching on the filenames in a directory, just as the variousshells do.</p></blockquote><p><a name="INDEX-761"></a><a name="INDEX-762"></a> Whether you use the<tt class="literal">glob</tt> function or the old angle-bracket form, thefileglob operator also does <tt class="literal">while</tt> magic like theline input operator, assigning the result to <tt class="literal">$_</tt>.(That was the rationale for overloading the angle operator in thefirst place.) For example, if you wanted to change the permissions onall your C code files, you might say:<blockquote><pre class="programlisting">while (glob "*.c") { chmod 0644, $_;}</pre></blockquote>which is equivalent to:<blockquote><pre class="programlisting">while (<*.c>) { chmod 0644, $_;}</pre></blockquote>The <tt class="literal">glob</tt> function was originally implemented as ashell command in older versions of Perl (and in even older versions ofUnix), which meant it was comparatively expensive to execute and,worse still, wouldn't work exactly the same everywhere. Nowadays it'sa built-in, so it's more reliable and a lot faster. See thedescription of the <tt class="literal">File::Glob</tt> module in<a href="ch32_01.htm">Chapter 32, "Standard Modules"</a> for how to alter the defaultbehavior of this operator, such as whether to treat spaces in itsoperand (argument) as pathname separators, whether to expand tildes orbraces, whether to be case insensitive, and whether to sort the returnvalues--amongst other things.</p><p>Of course, the shortest and arguably the most readable way to do the<tt class="literal">chmod</tt> command above is to use the fileglob as a list operator:<blockquote><pre class="programlisting">chmod 0644, <*.c>;</pre></blockquote>A fileglob evaluates its (embedded) operand only when starting a newlist. All values must be read before the operator will start over.In a list context, this isn't important because you automatically getthem all anyway. In a scalar context, however, the operator returnsthe next value each time it is called, or a false value if you've justrun out. Again, false is returned only once. So if you're expectinga single value from a fileglob, it is much better to say:<blockquote><pre class="programlisting">($file) = <blurch*>; # list context</pre></blockquote>than to say:<blockquote><pre class="programlisting">$file = <blurch*>; # scalar context</pre></blockquote>because the former returns all matched filenames and resets theoperator, whereas the latter alternates between returning filenamesand returning false.</p><p><a name="INDEX-763"></a><a name="INDEX-764"></a>If you're trying to do variable interpolation, it's definitely betterto use the <tt class="literal">glob</tt> operator because the older notation can causeconfusion with the indirect filehandle notation.This is where itbecomes apparent that the borderline between terms and operators is abit mushy:<blockquote><pre class="programlisting">@files = <$dir/*.[ch]>; # Works, but avoid.@files = glob("$dir/*.[ch]"); # Call glob as function.@files = glob $some_pattern; # Call glob as operator.</pre></blockquote><a name="INDEX-765"></a><a name="INDEX-766"></a></p><p>We left the parentheses off of the last example to illustrate that<tt class="literal">glob</tt> can be used either as a function (a term) or as a <em class="emphasis">unary</em>operator; that is, a prefix operator that takes a single argument. The<tt class="literal">glob</tt> operator is an example of a <em class="emphasis">named unary operator</em>, which isjust one kind of operator we'll talk about in the next chapter. Later,we'll talk about pattern-matching operators, which also parse liketerms but behave like operators.</p><!-- BOTTOM NAV BAR --><hr width="515" align="left"><div class="navbar"><table width="515" border="0"><tr><td align="left" valign="top" width="172"><a href="ch02_10.htm"><img src="../gifs/txtpreva.gif" alt="Previous" border="0"></a></td><td align="center" valign="top" width="171"><a href="index.htm"><img src="../gifs/txthome.gif" alt="Home" border="0"></a></td><td align="right" valign="top" width="172"><a href="ch03_01.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr><tr><td align="left" valign="top" width="172">2.10. Typeglobs and Filehandles</td><td align="center" valign="top" width="171"><a href="index/index.htm"><img src="../gifs/index.gif" alt="Book Index" border="0"></a></td><td align="right" valign="top" width="172">3. Unary and Binary Operators</td></tr></table></div><hr width="515" align="left"><!-- LIBRARY NAV BAR --><img src="../gifs/smnavbar.gif" usemap="#library-map" border="0" alt="Library Navigation Links"><p><font size="-1"><a href="copyrght.htm">Copyright © 2001</a> O'Reilly & Associates. All rights reserved.</font></p><map name="library-map"> <area shape="rect" coords="2,-1,79,99" href="../index.htm"><area shape="rect" coords="84,1,157,108" href="../perlnut/index.htm"><area shape="rect" coords="162,2,248,125" href="../prog/index.htm"><area shape="rect" coords="253,2,326,130" href="../advprog/index.htm"><area shape="rect" coords="332,1,407,112" href="../cookbook/index.htm"><area shape="rect" coords="414,2,523,103" href="../sysadmin/index.htm"></map><!-- END OF BODY --></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -