📄 ch18.htm
字号:
<BR>
16 }<BR>
17 #<BR>
18 # Keep any changes, if any, in hash back on disk.<BR>
19 #<BR>
20 dbmclose(%stocks);</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Line 13 opens the hash as before. Because the file already exists,
there is no need to create it. Lines 14 and 15 are where the contents
of the hash <TT><FONT FACE="Courier">$stocks</FONT></TT> is printed
out. Line 20 closes the file.
<H2><A NAME="AddingandRemovingItems"><FONT SIZE=5 COLOR=#FF0000>Adding
and Removing Items</FONT></A></H2>
<P>
It's relatively simple to add a new symbol to the newly created
database. To see how to add to the database, refer to Listing
18.3.
<HR>
<BLOCKQUOTE>
<B>Listing 18.3. Adding to the DBM array.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2 # --------------------------------------------------------
<BR>
3 # Sample script to add to contents of a DBM repository.
<BR>
4 # --------------------------------------------------------
<BR>
5 #<BR>
6 # Use the default DBM utilites<BR>
7 #<BR>
8 use AnyDBM_File;<BR>
9 #<BR>
10 # Open the database "ticker". (If it does not exist,
create it.)<BR>
11 # Map the hash stocks to this database.<BR>
12 #<BR>
13 dbmopen(%stocks,"ticker",0666);<BR>
14 print "\n Symbol: ";<BR>
15 # Get the symbol for the company <BR>
16 chop ($symbol = <STDIN>);<BR>
17 print "\n Company Name: ";<BR>
18 # Get the name of the company <BR>
19 chop ($name = <STDIN>);<BR>
20 $stocks{$symbol} = $name;<BR>
21 # Keep any changes, if any, in hash back on disk.<BR>
22 #<BR>
23 dbmclose(%stocks);</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
To delete an item from the <TT><FONT FACE="Courier">%stocks{}</FONT></TT>
associative array, use the <TT><FONT FACE="Courier">delete</FONT></TT>
command. For example, the code in Listing 18.3 can be modified
to become a deletion command by adding the <TT><FONT FACE="Courier">delete</FONT></TT>
operator to line 20. The code in line 20 would look like this:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">delete $stocks{$symbol};</FONT></TT>
</BLOCKQUOTE>
<H2><A NAME="OperationsonaDBMFile"><FONT SIZE=5 COLOR=#FF0000>Operations
on a DBM File</FONT></A></H2>
<P>
The contents of a DBM array can be easily searched using Perl's
features. To look for a symbol in an existing DBM, use the Perl
search operation with the <TT><FONT FACE="Courier">=~ //</FONT></TT>
syntax. Listing 18.5 illustrates this.
<HR>
<BLOCKQUOTE>
<B>Listing 18.5. Searching the DBM array.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2 # --------------------------------------------------------
<BR>
3 # Sample script to search contents of a DBM repository.
<BR>
4 # --------------------------------------------------------
<BR>
5 #<BR>
6 # Use the default DBM utilites<BR>
7 #<BR>
8 use AnyDBM_File;<BR>
9 #<BR>
10 # Open the database "ticker". (If it does not exist,
create it.)<BR>
11 # Map the hash stocks to this database.<BR>
12 #<BR>
13 dbmopen(%stocks,"ticker",0666);<BR>
14 print "\n Enter String to Look for: ";<BR>
15 $search = <STDIN>;<BR>
16 chop $search;<BR>
17 printf "\n Searching.\n";<BR>
18 $i = 0;<BR>
19 while (($symbol,$name) = each(%stocks)) {<BR>
20 if ($name =~ /$search/) {<BR>
21 $i++;
<BR>
22 print
"$i. [$symbol] has [$name]\n"<BR>
23 }<BR>
24 }<BR>
25 printf "\n ===> $i Records found.\n ";<BR>
26 #<BR>
27 # Keep any changes, if any, in hash back on disk.<BR>
28 #<BR>
29 dbmclose(%stocks);</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Lines 19 through 24 contain a <TT><FONT FACE="Courier">while</FONT></TT>
loop that uses the <TT><FONT FACE="Courier">each</FONT></TT> command.
The <TT><FONT FACE="Courier">each</FONT></TT> command is more
efficient than using a <TT><FONT FACE="Courier">for</FONT></TT>
loop command because both the key and the indexed value are retrieved
with the <TT><FONT FACE="Courier">each</FONT></TT> command. In
the <TT><FONT FACE="Courier">for </FONT></TT>loop on the keys
of an associative array, two separate steps must be taken to retrieve
the same information-first to get the key for the loop iteration
with a call to the<I> keys(hash)</I> function, and second to get
the value based on the retrieved key.
<P>
Running the program to look for <TT><FONT FACE="Courier">NAL</FONT></TT>
in the company names produces the following output:
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> Enter String to Look for: <B>NAL
<BR>
</B> Searching.<BR>
1. [ALOG] has [ANALOGIC CORP]<BR>
2. [AATI] has [ANALYSIS & TEchNOLOGY]<BR>
3. [ANLY] has [ANALYSTS INTL CORP]<BR>
4. [APSG] has [APPLIED SIGNAL TEch]<BR>
5. [ADI] has [ANALOG DEVICES]<BR>
<BR>
===> 5 Records found.</FONT></TT>
</BLOCKQUOTE>
<P>
The program found all company names with the string <TT><FONT FACE="Courier">NAL</FONT></TT>
in their name. As you can see, within Perl you have the power
to create a new database, add or delete items from the database,
and list the contents of the database. Using the hash as the map,
you can perform many other operations on the hash and reflect
the results back to disk.
<P>
The DBM files are still a flat database; therefore, in order to
create relationships between data items, you still have to do
some shuffling around of indexes, filenames, and files. Fairly
sophisticated data algorithms are not out of reach, however, if
you are careful. For example, the sample <TT><FONT FACE="Courier">$symbol</FONT></TT>
index can also be used as a filename containing historical data.
Let's say the <TT><FONT FACE="Courier">%stocks{}</FONT></TT> DBM
array is used as a storage area for the stocks in a portfolio.
It's easy to get historical data from the Internet (for example,
via CompuServe) for a given stock symbol. Listing 18.5 collects
and displays some statistics for the symbols in the sample portfolio.
<P>
So that you don't have to type everything via <TT><FONT FACE="Courier">STDIN</FONT></TT>,
the script is designed to use command-line options with the <TT><FONT FACE="Courier">Getopts::Long</FONT></TT>
module. <A HREF="ch16.htm" tppabs="http://www.mcp.com/815097600/0-672/0-672-30891-6/ch16.htm" >See Chapter 16</A>, "Command-Line
Interface with Perl," for more information on how to use
the <TT><FONT FACE="Courier">Getopts::Long.pm</FONT></TT> module.
In this example, the <TT><FONT FACE="Courier">-s</FONT></TT> option
is used to specify the stock symbol and the <TT><FONT FACE="Courier">-v</FONT></TT>
option is used to get a complete listing of all the readings.
<HR>
<BLOCKQUOTE>
<B>Listing 18.4. Using the DBM array.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2 # --------------------------------------------------------
<BR>
3 # Sample script to use the DBM array for indexing.<BR>
4 # --------------------------------------------------------
<BR>
5 #<BR>
6 # Use the default DBM utilites<BR>
7 #<BR>
8 use AnyDBM_File;<BR>
9 use Getopt::Long;<BR>
10 #<BR>
11 # Open the database "ticker". (If it does not exist,
create it.)<BR>
12 # Map the hash stocks to this database.<BR>
13 #<BR>
14 dbmopen(%stocks,"ticker",0666);<BR>
15 #print "\n Enter Symbol to Look for: ";<BR>
16 #$search = <STDIN>;<BR>
17 #chop $search;<BR>
18 GetOptions('stock=s','v!');<BR>
19 $search = $opt_stock;<BR>
20 $i = 0;<BR>
21 $highest = 0;<BR>
22 $lowest = 10000;<BR>
23 if ($stocks{$search}) {<BR>
24 if (-e $search) {<BR>
25 open(SDATA,$search)
|| die "Cannot open $search $!\n";<BR>
26 printf
"\n Historical data for $search \n" if ($opt_v);<BR>
27 while
(<SDATA>) {<BR>
28
($day,$hi,$lo,$close) = split('\s',$_);<BR>
29
$sum += $close;<BR>
30
$i++;<BR>
31
if ($hi > $highest) { $highest = $hi; }<BR>
32
if ($lo < $lowest) { $lowest = $lo; }<BR>
33
write if ($opt_v);<BR>
34 }<BR>
35 close
SDATA;<BR>
36 printf "\n
Summay of %d readings on $search", $i;<BR>
37 printf
"\n Lowest On File = %f ", $lowest;<BR>
38 printf
"\n Highest On File = %f ", $highest;<BR>
39 printf
"\n Average Price = %f ", $sum / $i;
<BR>
40 printf
"\n";<BR>
41 }<BR>
42 } else {<BR>
43 printf "\n Sorry, I do not track
this symbol: $symbol";<BR>
44 }<BR>
45<BR>
46 dbmclose(%stocks);<BR>
47 #<BR>
48 # Define a clean output format for displaying data<BR>
49 #.<BR>
50 format STDOUT =<BR>
51 @<<<<<< @####.### @####.### @####.###
<BR>
52 $day, $hi, $lo, $close<BR>
53 .</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
You print the stocks you are tracking by checking to see if the
name exists in the <TT><FONT FACE="Courier">%stocks{}</FONT></TT>
hash. This is done in line 23 with the following statement:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">if ($stocks{$search}) {</FONT></TT>
</BLOCKQUOTE>
<P>
Once the file is found to exist with the <TT><FONT FACE="Courier">-e</FONT></TT>
flag in line 24, it is opened and read from in lines 27 to 35.
The summary is printed in lines 36 through 40. In case the symbol
is not listed in the database, an error message is printed in
the <TT><FONT FACE="Courier">else</FONT></TT> clause in line 43.
The format for the output via the <TT><FONT FACE="Courier">write</FONT></TT>
statement in line 33 is defined in lines 50 to 53.
<P>
In this example, the historical data for a stock is stored in
a file called <TT><FONT FACE="Courier">AMAT</FONT></TT>. Therefore,
to invoke the script, use this command:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$<B> test.pl -s AMAT<BR>
<BR>
</B>Summay of 305 readings on AMAT<BR>
Lowest On File = 18.500000<BR>
Highest On File = 59.875000<BR>
Average Price = 38.879393</FONT></TT>
</BLOCKQUOTE>
<P>
As you can see, the output from this script is made a bit more
presentable with the use of the <TT><FONT FACE="Courier">format</FONT></TT>
statement.
<H2><A NAME="UsingDBMinModules"><FONT SIZE=5 COLOR=#FF0000>Using
DBM in Modules</FONT></A></H2>
<P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -