📄 ch9.htm
字号:
print();
}
while (<>) {
print();
}
</PRE>
</BLOCKQUOTE>
<P>
Perl will create the <TT>@ARGV</TT>
array from the command line. Each file name on the command line-after
the program name-will be added to the <TT>@ARGV</TT>
array as an element. When the program runs the diamond operator
starts reading from the file name in the first element of the
array. When that entire file has been read, the next file is read
from, and so on, until all of the elements have been used. When
the last file has be finished, the <TT>while</TT>
loop will end.
<P>
Using the diamond operator to iterate over a list of file names
is very handy. You can use it in the middle of your program by
explicitly assigning a list of file names to the <TT>@ARGV</TT>
array. Listing 9.3 shows what this might look like in a program.
<HR>
<BLOCKQUOTE>
<B>Listing 9.3 09LST03.PL-Read from Multiple Files
Using the @ARGV Array<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
@ARGV = ("09lst01.pl", "09lst02.pl");
while (<>) {
print();
}
</PRE>
</BLOCKQUOTE>
<HR>
<P>
This program displays:<BR>
<BLOCKQUOTE>
<PRE>
while (<STDIN>) {
print();
}
while (<>) {
print();
}
</PRE>
</BLOCKQUOTE>
<P>
Next, we will take a look at the ways that Perl lets you test
files, and following that, the fuNCtions that can be used with
files.
<H2><A NAME="FileTestOperators"><FONT SIZE=5 COLOR=#FF0000>
File Test Operators</FONT></A></H2>
<P>
Perl has many operators that you can use to test different aspects
of a file. For example, you can use the <TT>-e</TT>
operator to ensure that a file exists before deleting it. Or,
you can check that a file can be written to before appending to
it. By checking the feasibility of the impending file operation,
you can reduce the number of errors that your program will eNCounter.
Table 9.2 shows a complete list of the operators used to test
files.<BR>
<P>
<CENTER><B>Table 9.2 Perl's File Test Operators</B></CENTER>
<p>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD WIDTH=121><I>Operator</I></TD><TD WIDTH=469><I>Description</I>
</TD></TR>
<TR><TD WIDTH=121><TT>-A</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Returns the access age of <TT>OPERAND</TT> when the program started.
</TD></TR>
<TR><TD WIDTH=121><TT>-b</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> is a block device.
</TD></TR>
<TR><TD WIDTH=121><TT>-B</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> is a binary file. If <TT>OPERAND</TT> is a file handle, then the current buffer is examined, instead of the file itself.
</TD></TR>
<TR><TD WIDTH=121><TT>-c OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> is a character device.
</TD></TR>
<TR><TD WIDTH=121><TT>-C</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Returns the inode change age of <TT>OPERAND</TT> when the program started.
</TD></TR>
<TR><TD WIDTH=121><TT>-d</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> is a directory.
</TD></TR>
<TR><TD WIDTH=121><TT>-e</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> exists.
</TD></TR>
<TR><TD WIDTH=121><TT>-f</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> is a regular file as opposed to a directory, symbolic link or other type of file.
</TD></TR>
<TR><TD WIDTH=121><TT>-g</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> has the setgid bit set.
</TD></TR>
<TR><TD WIDTH=121><TT>-k</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> has the sticky bit set.
</TD></TR>
<TR><TD WIDTH=121><TT>-l</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> is a symbolic link. Under DOS, this operator always will return false.
</TD></TR>
<TR><TD WIDTH=121><TT>-M</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Returns the age of <TT>OPERAND</TT> in days when the program started.
</TD></TR>
<TR><TD WIDTH=121><TT>-o</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> is owned by the effective uid. Under DOS, it always returns true.
</TD></TR>
<TR><TD WIDTH=121><TT>-O</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> is owned by the read uid/gid. Under DOS, it always returns true.
</TD></TR>
<TR><TD WIDTH=121><TT>-p</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> is a named pipe.
</TD></TR>
<TR><TD WIDTH=121><TT>-r</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> can be read from.
</TD></TR>
<TR><TD WIDTH=121><TT>-R</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> can be read from by the real uid/gid. Under DOS, it is identical to -r.
</TD></TR>
<TR><TD WIDTH=121><TT>-s</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Returns the size of <TT>OPERAND</TT> in bytes. Therefore, it returns true if <TT>OPERAND</TT> is non-zero.
</TD></TR>
<TR><TD WIDTH=121><TT>-S</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> is a socket.
</TD></TR>
<TR><TD WIDTH=121><TT>-t</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> is opened to a tty.
</TD></TR>
<TR><TD WIDTH=121><TT>-T</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> is a text file. If <TT>OPERAND</TT> is a file handle, then the current buffer is examined, instead of the file itself.
</TD></TR>
<TR><TD WIDTH=121><TT>-u</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> has the setuid bit set.
</TD></TR>
<TR><TD WIDTH=121><TT>-w</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> can be written to.
</TD></TR>
<TR><TD WIDTH=121><TT>-W</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> can be written to by the real uid/gid. Under DOS, it is identical to -w.
</TD></TR>
<TR><TD WIDTH=121><TT>-x</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> can be executed.
</TD></TR>
<TR><TD WIDTH=121><TT>-X</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> can be executed by the real uid/gid. Under DOS, it is identical to -x.
</TD></TR>
<TR><TD WIDTH=121><TT>-z</TT> <TT>OPERAND</TT>
</TD><TD WIDTH=469>Tests if <TT>OPERAND</TT> size is zero.
</TD></TR>
</TABLE>
</CENTER>
<P>
<p>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Note</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
If the <TT>OPERAND</TT> is not specified in the file test, the <TT>$ </TT>variable will be used instead.
</BLOCKQUOTE>
</TD></TR>
</TABLE>
</CENTER>
<P>
<P>
The operand used by the file tests can be either a file handle
or a file name. The file tests work by internally calling the
operating system to determine information about the file in question.
The operators will evaluate to true if the test succeeds and false
if it does not.
<P>
If you need to perform two or more tests on the same file, you
use the special underscore (<TT>_</TT>)
file handle. This tells Perl to use the file information for the
last system query and saves time. However, the underscore file
handle does have some caveats. It does not work with the <TT>-t</TT>
operator. In addition, the <TT>lstat()</TT>
fuNCtion and <TT>-l</TT> test will
leave the system buffer filled with information about a symbolic
link, not a real file.
<P>
The <TT>-T</TT> and <TT>-B</TT>
file tests will examine the first block or so of the file. If
more than 10 percent of the bytes are non-characters or if a null
byte is eNCountered, then the file is considered a binary file.
<I>Binary</I> files are normally data files, as opposed to text
or human-readable files. If you need to work with binary files,
be sure to use the <TT>binmode()</TT>
file fuNCtion, which is described in the section, "Example:
Binary Files," later in this chapter.
<H3><A NAME="ExampleUsingFileTests">
Example: Using File Tests</A></H3>
<P>
For our first example with file tests, let's examine a list of
files from the command line and determine if each is a regular
file or a special file.
<P>
<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>
<BLOCKQUOTE>
<I>Start a </I><TT><I>foreach</I></TT><I>
loop that looks at the command line array. Each element in the
array is assigned to the default loop variable </I><TT><I>$_</I></TT><I>.
<BR>
Print the file name contained in </I><TT><I>$_</I></TT><I>.
<BR>
Print a message indicating the type of file by checking the evaluation
of the </I><TT><I>-f</I></TT><I> operator.</I>
</BLOCKQUOTE>
<HR>
<BLOCKQUOTE>
<B>Listing 9.4 09LST04.PL-Using the </B><TT><I><B><FONT FACE="Courier">-f</FONT></B></I></TT><B>
Operator to Find Regular Files Inside a </B><TT><I><B><FONT FACE="Courier">foreach</FONT></B></I></TT><B>
Loop<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
foreach (@ARGV) {
print;
print((-f) ? " -REGULAR\n" : " -SPECIAL\n")
}
</PRE>
</BLOCKQUOTE>
<HR>
<P>
When this program is run using the following command line:
<BLOCKQUOTE>
<PRE>
perl -w 09lst01.pl \perl5 perl.exe \windows
</PRE>
</BLOCKQUOTE>
<P>
the following is displayed:
<BLOCKQUOTE>
<PRE>
09lst01.pl -REGULAR
\perl5 -SPECIAL
perl.exe -REGULAR
\windows -SPECIAL
</PRE>
</BLOCKQUOTE>
<P>
Each of the directories listed on the command line were recognized
as special files. If you want to ignore all special files in the
command line, you do so like this:
<P>
<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>
<BLOCKQUOTE>
<I>Start a </I><TT><I>foreach</I></TT><I>
loop that looks at the command line array.<BR>
If the current file is special, then skip it and go on to the
next iteration of the </I><TT><I>foreach</I></TT><I>
loop.<BR>
Print the current file name that is contained in </I><TT><I>$_</I></TT><I>.
<BR>
Print a message indicating the type of file.</I>
</BLOCKQUOTE>
<HR>
<BLOCKQUOTE>
<B>Listing 9.5 09LST05.PL-Using the </B><TT><I><B><FONT FACE="Courier">-f</FONT></B></I></TT><B>
Operator to Find Regular Files Inside a </B><TT><I><B><FONT FACE="Courier">foreach</FONT></B></I></TT><B>
Loop<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
foreach (@ARGV) {
next unless -f; # ignore all non-normal files.
print;
print((-f) ? " -REGULAR\n" : " -SPECIAL\n")
}
</PRE>
</BLOCKQUOTE>
<HR>
<P>
When this program is run using the following command line:
<BLOCKQUOTE>
<PRE>
perl -w 09lst01.pl \perl perl.exe \windows
</PRE>
</BLOCKQUOTE>
<P>
the following is displayed:
<BLOCKQUOTE>
<PRE>
09lst01.pl -REGULAR
perl.exe -REGULAR
</PRE>
</BLOCKQUOTE>
<P>
Notice that only the regular file names are displayed. The two
directories on the command line were ignored.
<P>
As mentioned above, you can use the underscore file handle to
make two tests in a row on the same file so that your program
can execute faster and use less system resources. This could be
important if your application is time critical or makes many repeated
tests on a large number of files.
<P>
<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>
<BLOCKQUOTE>
<I>Start a </I><TT><I>foreach</I></TT><I>
loop that looks at the command line array.<BR>
If the current file is special, then skip it and go on to the
next iteration of the </I><TT><I>foreach</I></TT><I>
loop.<BR>
Determine the number of bytes in the file with the </I><TT><I>-s</I></TT><I>
operator using the underscore file handle so that a second operating
system call is not needed.<BR>
Print a message indicating the name and size of the file.</I>
</BLOCKQUOTE>
<HR>
<BLOCKQUOTE>
<B>Listing 9.6 09LST06.PL-Finding the Size in Bytes
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -