📄 ch19.htm
字号:
<TR VALIGN=TOP><TD WIDTH=100><CENTER><TT><FONT FACE="Courier">$-</FONT></TT></CENTER>
</TD><TD WIDTH=513>This variable contains the number of lines left on the page. When <TT><FONT FACE="Courier">$-</FONT></TT> is equal to 0, it is set to <TT><FONT FACE="Courier">$=</FONT></TT>, and the next line output triggers the top-of-page format. The
value in <TT><FONT FACE="Courier">$-</FONT></TT> is incremented every time you write to the file handle associated with the current format.
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=100><CENTER><TT><FONT FACE="Courier">$%</FONT></TT></CENTER>
</TD><TD WIDTH=513>This variable contains the current page number. You can refer to the value in this variable to print page numbers in your output.
</TD></TR>
</TABLE></CENTER>
<P>
<P>
Listing 19.9 is a simple program that provides a clean listing
of a lengthy source file. There are two options to this program:
<TT><FONT FACE="Courier">-file</FONT></TT> to specify the filename
and <TT><FONT FACE="Courier">-line</FONT></TT> to specify the
number of lines per page.
<HR>
<BLOCKQUOTE>
<B>Listing 19.9. A sample program to list files.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2 use Getopt::Long;<BR>
3 $result = GetOptions('file=s','lines:i');<BR>
4 if !defined($opt_file)<BR>
{ print
"Usage: $0 filename\n ";<BR>
exit 0;
}<BR>
5 open(SFILE,$opt_file) || die "Cannot open $opt_file
\!\n";<BR>
6 $= = $opt_lines ? $opt_lines : 50;<BR>
7 $date = `date +%D`;<BR>
8 chop($date);<BR>
9 $i = 0;<BR>
10 while (<SFILE>) {<BR>
11 write;<BR>
12 $i++;<BR>
13 }<BR>
14 close(SFILE);<BR>
15 format STDOUT_TOP =<BR>
16 Filename @<<<<<<<<<<<<<< Date
@<<<<<<<< Page: @#####<BR>
17 $opt_file, $date, $%<BR>
18 =======================================================<BR>
19 .<BR>
20 format STDOUT =<BR>
21 @#### @*<BR>
22 $i,$_<BR>
23 .</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
The code in Listing 19.9 uses the <TT><FONT FACE="Courier">Getopts</FONT></TT>
module to collect the filename and the number of lines per page.
If you are not familiar with the use of the <TT><FONT FACE="Courier">Getopts</FONT></TT>
module, please refer to <A HREF="ch16.htm" tppabs="http://www.mcp.com/815097600/0-672/0-672-30891-6/ch16.htm" >Chapter 16</A>, "Command-line
Interface with Perl," for more details. The variable <TT><FONT FACE="Courier">$opt_file</FONT></TT>
contains the filename, and <TT><FONT FACE="Courier">$opt_lines</FONT></TT>
(if defined) contains the number of lines per page.
<P>
In line 6 the variable <TT><FONT FACE="Courier">$=</FONT></TT>
is set to the number of lines per page requested by the user.
The default value is set to 55 lines per page. A date value is
generated and stored in <TT><FONT FACE="Courier">$date</FONT></TT>
on lines 7 and 8. The <TT><FONT FACE="Courier">$i</FONT></TT>
counter is used to print out the line number in the source file.
<P>
Because the script is writing to <TT><FONT FACE="Courier">STDOUT</FONT></TT>
with the <TT><FONT FACE="Courier">write()</FONT></TT> command,
it uses the formats <TT><FONT FACE="Courier">STDOUT</FONT></TT>
and <TT><FONT FACE="Courier">STDOUT_TOP</FONT></TT> for the records
and page headers, respectively. In line 17 the script uses <TT><FONT FACE="Courier">$%</FONT></TT>
to print the current page count along with the filename and the
current date.
<P>
<TT><FONT FACE="Courier">@*</FONT></TT> in the field specifier
is used in line 18 to indicate that the entire value of the <TT><FONT FACE="Courier">$_</FONT></TT>
variable should be printed as a string. The <TT><FONT FACE="Courier">$_</FONT></TT>
variable is not truncated as it would be if the other string specifiers
such as <TT><FONT FACE="Courier">@<<<<</FONT></TT>,
<TT><FONT FACE="Courier">@>>>></FONT></TT>, or <TT><FONT FACE="Courier">@||||||</FONT></TT>
had been used.
<P>
In fact, <TT><FONT FACE="Courier">@*</FONT></TT> even allows multiline
fields. Had there been any carriage returns in the string, they
would also be printed out. Therefore, if the string <TT><FONT FACE="Courier">$_</FONT></TT>
is equal to <TT><FONT FACE="Courier">"One\nTwo\nThree\nFour"</FONT></TT>,
it is printed as follows when used in a <TT><FONT FACE="Courier">write()</FONT></TT>
function:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">One<BR>
Two<BR>
Three<BR>
Four</FONT></TT>
</BLOCKQUOTE>
<P>
To suppress the printing of a format top, you should define the
format top specification. To delay the printing, you can keep
resetting the value of <TT><FONT FACE="Courier">$-</FONT></TT>
to a non-zero value less than the value in <TT><FONT FACE="Courier">$=</FONT></TT>
as you print out text. When you are ready to print the top of
the header, set the value of <TT><FONT FACE="Courier">$- = 0</FONT></TT>
to signify the start of a new page.
<H2><A NAME="CreatingMultipleLineswiththeCaret"><FONT SIZE=5 COLOR=#FF0000>Creating
Multiple Lines with the Caret</FONT></A></H2>
<P>
There is more than one way to print long descriptive text in a
field. For instance, you could have multiple lines and use the
<TT><FONT FACE="Courier">@*</FONT></TT> specifier. The problem
is that you are not able to control the number of columns in the
output at all. To fill in multiple lines, you have to use the
caret (<TT><FONT FACE="Courier">^</FONT></TT>) operator instead
of the at (<TT><FONT FACE="Courier">@</FONT></TT>) operator. Using
the <TT><FONT FACE="Courier">^</FONT></TT> operator enables you
to specify the same text on multiple lines. Perl chops up the
variable for you and presents as much as it can per line.
<P>
The <TT><FONT FACE="Courier">^</FONT></TT> operator behaves the
same way as the <TT><FONT FACE="Courier">@</FONT></TT> operator
with one major difference: You can only use scalars with the <TT><FONT FACE="Courier">^</FONT></TT>
symbol. The reason for this is that the scalar value being mapped
to the <TT><FONT FACE="Courier">^</FONT></TT> format is chopped
up into manageable pieces for printing. It's nearly impossible
to do the chopping on an evaluated expression.
<P>
There are two ways that you can use the <TT><FONT FACE="Courier">^</FONT></TT>
operator: to output only a fixed number of lines or output only
as much as necessary. To output up to a fixed number of lines,
you use the tilde (<TT><FONT FACE="Courier">~</FONT></TT>) operator.
Here's the syntax to print the contents of the <TT><FONT FACE="Courier">$desc</FONT></TT>
variable using up to three lines:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">@<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<
<BR>
$hours, $desc
<BR>
~ ^<<<<<<<<<<<<<<<<<<<<<<<<
<BR>
$desc
<BR>
~ ^<<<<<<<<<<<<<<<<<<<<<<<<
<BR>
$desc</FONT></TT>
</BLOCKQUOTE>
<P>
If you omit the tildes, you will get exactly three lines of output.
The tildes suppress blank lines from being output, so therefore
you get up to three lines of output.
<P>
The tilde operator is required at the front of the line. You must
specify the <TT><FONT FACE="Courier">$desc</FONT></TT> variable
on every line that you want it divided on using the <TT><FONT FACE="Courier">^</FONT></TT>
operator. If you are not sure of how many lines you'll be printing,
you can use two tildes (<TT><FONT FACE="Courier">~~</FONT></TT>)
together. Listing 19.10 presents a sample invoice-printing program
using the padding field with two tildes.
<HR>
<BLOCKQUOTE>
<B>Listing 19.10. Using the tilde to print on multiple lines.
<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2 use Getopt::Long;<BR>
3 $result = GetOptions('file=s','invoice=i');<BR>
4 if($opt_file eq undef) { print "Usage: $_[0] filename\n
"; exit 0; }<BR>
5 open(SFILE,$opt_file) || die "Cannot open $opt_file
\!\n";<BR>
6 $date = `date +%D`;<BR>
7 chop($date);<BR>
8 $i = $opt_invoice ? $opt_invoice : 200;<BR>
9 $rate = 55;<BR>
10 while (<SFILE>) {<BR>
11 ($name,$addr,$hours,$desc)=
split(':');<BR>
12 $i++;<BR>
13 write;<BR>
14 }<BR>
15 close(SFILE);<BR>
16 format STDOUT =<BR>
17 INVOICE#@#######
<BR>
18 $i,<BR>
19 To:<BR>
20 @<<<<<<<<<<<<<<< My
Company<BR>
21 $name<BR>
22 @<<<<<<<<<<<<<<< Any
town, USA 99999<BR>
23 $addr<BR>
24 ==================================================================
<BR>
25 DESCRIPTION
<BR>
26 ==================================================================
<BR>
27
@<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<
<<<<<<<<<<<
<BR>
28 $name, $desc<BR>
29 ~~
^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<BR>
30 $desc<BR>
31
Total Hours @######<BR>
32 $hours<BR>
33 ==================================================================
<BR>
34
Total Due $ @######<BR>
35 $hours * $rate<BR>
36 ==================================================================
<BR>
37 Have a nice day!<BR>
38 .</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
The important lines in Listing 19.10 are lines 27 through 35.
Lines 27 through 30 are used to specify the format for the client
name and description fields. Note the use of the two tildes (<TT><FONT FACE="Courier">~~</FONT></TT>)
in the line to format the <TT><FONT FACE="Courier">$desc</FONT></TT>
variable. Line 30 allows Perl to expand the output to multiple
lines. Lines 31 through 35 print out the totals in their own lines.
<P>
Here is the output of Listing 19.10. The input file is not shown.
<BLOCKQUOTE>
<TT><FONT FACE="Courier">
INVOICE# 201<BR>
<BR>
To:<BR>
El Dictator Corp My
Company<BR>
South of Here Any
town, USA 99999<BR>
<BR>
==================================================================
<BR>
DESCRIPTION
<BR>
==================================================================
<BR>
El Dictator Corp Revolutions
quelled,<BR>
uprisings started, lions<BR>
&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -