perlreftut.html
来自「perl教程」· HTML 代码 · 共 546 行 · 第 1/3 页
HTML
546 行
</pre>
<pre>
<span class="variable">$href</span> <span class="operator">=</span> <span class="operator">{</span> <span class="string">APR</span> <span class="operator">=></span> <span class="number">4</span><span class="operator">,</span> <span class="string">AUG</span> <span class="operator">=></span> <span class="number">8</span> <span class="operator">}</span><span class="operator">;</span>
<span class="comment"># $href now holds a reference to a hash</span>
</pre>
<p>The references you get from rule 2 are the same kind of
references that you get from rule 1:</p>
<pre>
<span class="comment"># This:</span>
<span class="variable">$aref</span> <span class="operator">=</span> <span class="operator">[</span> <span class="number">1</span><span class="operator">,</span> <span class="number">2</span><span class="operator">,</span> <span class="number">3</span> <span class="operator">]</span><span class="operator">;</span>
</pre>
<pre>
<span class="comment"># Does the same as this:</span>
<span class="variable">@array</span> <span class="operator">=</span> <span class="operator">(</span><span class="number">1</span><span class="operator">,</span> <span class="number">2</span><span class="operator">,</span> <span class="number">3</span><span class="operator">);</span>
<span class="variable">$aref</span> <span class="operator">=</span> <span class="operator">\</span><span class="variable">@array</span><span class="operator">;</span>
</pre>
<p>The first line is an abbreviation for the following two lines, except
that it doesn't create the superfluous array variable <code>@array</code>.</p>
<p>If you write just <code>[]</code>, you get a new, empty anonymous array.
If you write just <code>{}</code>, you get a new, empty anonymous hash.</p>
<p>
</p>
<h2><a name="using_references">Using References</a></h2>
<p>What can you do with a reference once you have it? It's a scalar
value, and we've seen that you can store it as a scalar and get it back
again just like any scalar. There are just two more ways to use it:</p>
<p>
</p>
<h3><a name="use_rule_1"><strong>Use Rule 1</strong></a></h3>
<p>You can always use an array reference, in curly braces, in place of
the name of an array. For example, <code>@{$aref}</code> instead of <code>@array</code>.</p>
<p>Here are some examples of that:</p>
<p>Arrays:</p>
<pre>
<span class="variable">@a</span> <span class="variable">@</span><span class="operator">{</span><span class="variable">$aref</span><span class="operator">}</span> <span class="variable">An</span> <span class="variable">array</span>
<span class="keyword">reverse</span> <span class="variable">@a</span> <span class="keyword">reverse</span> <span class="variable">@</span><span class="operator">{</span><span class="variable">$aref</span><span class="operator">}</span> <span class="variable">Reverse</span> <span class="variable">the</span> <span class="variable">array</span>
<span class="variable">$a</span><span class="operator">[</span><span class="number">3</span><span class="operator">]</span> <span class="variable">$</span><span class="operator">{</span><span class="variable">$aref</span><span class="operator">}[</span><span class="number">3</span><span class="operator">]</span> <span class="variable">An</span> <span class="variable">element</span> <span class="variable">of</span> <span class="variable">the</span> <span class="variable">array</span>
<span class="variable">$a</span><span class="operator">[</span><span class="number">3</span><span class="operator">]</span> <span class="operator">=</span> <span class="number">17</span><span class="operator">;</span> <span class="variable">$</span><span class="operator">{</span><span class="variable">$aref</span><span class="operator">}[</span><span class="number">3</span><span class="operator">]</span> <span class="operator">=</span> <span class="number">17</span> <span class="variable">Assigning</span> <span class="variable">an</span> <span class="variable">element</span>
</pre>
<p>On each line are two expressions that do the same thing. The
left-hand versions operate on the array <code>@a</code>. The right-hand
versions operate on the array that is referred to by <code>$aref</code>. Once
they find the array they're operating on, both versions do the same
things to the arrays.</p>
<p>Using a hash reference is <em>exactly</em> the same:</p>
<pre>
<span class="variable">%h</span> <span class="variable">%</span><span class="operator">{</span><span class="variable">$href</span><span class="operator">}</span> <span class="variable">A</span> <span class="variable">hash</span>
<span class="keyword">keys</span> <span class="variable">%h</span> <span class="keyword">keys</span> <span class="variable">%</span><span class="operator">{</span><span class="variable">$href</span><span class="operator">}</span> <span class="variable">Get</span> <span class="variable">the</span> <span class="keyword">keys</span> <span class="variable">from</span> <span class="variable">the</span> <span class="variable">hash</span>
<span class="variable">$h</span><span class="operator">{</span><span class="string">'red'</span><span class="operator">}</span> <span class="variable">$</span><span class="operator">{</span><span class="variable">$href</span><span class="operator">}{</span><span class="string">'red'</span><span class="operator">}</span> <span class="variable">An</span> <span class="variable">element</span> <span class="variable">of</span> <span class="variable">the</span> <span class="variable">hash</span>
<span class="variable">$h</span><span class="operator">{</span><span class="string">'red'</span><span class="operator">}</span> <span class="operator">=</span> <span class="number">17</span> <span class="variable">$</span><span class="operator">{</span><span class="variable">$href</span><span class="operator">}{</span><span class="string">'red'</span><span class="operator">}</span> <span class="operator">=</span> <span class="number">17</span> <span class="variable">Assigning</span> <span class="variable">an</span> <span class="variable">element</span>
</pre>
<p>Whatever you want to do with a reference, <strong>Use Rule 1</strong> tells you how
to do it. You just write the Perl code that you would have written
for doing the same thing to a regular array or hash, and then replace
the array or hash name with <code>{$reference}</code>. "How do I loop over an
array when all I have is a reference?" Well, to loop over an array, you
would write</p>
<pre>
<span class="keyword">for</span> <span class="keyword">my</span> <span class="variable">$element</span> <span class="operator">(</span><span class="variable">@array</span><span class="operator">)</span> <span class="operator">{</span>
<span class="operator">...</span>
<span class="operator">}</span>
</pre>
<p>so replace the array name, <code>@array</code>, with the reference:</p>
<pre>
<span class="keyword">for</span> <span class="keyword">my</span> <span class="variable">$element</span> <span class="operator">(</span><span class="variable">@</span><span class="operator">{</span><span class="variable">$aref</span><span class="operator">}</span><span class="operator">)</span> <span class="operator">{</span>
<span class="operator">...</span>
<span class="operator">}</span>
</pre>
<p>"How do I print out the contents of a hash when all I have is a
reference?" First write the code for printing out a hash:</p>
<pre>
<span class="keyword">for</span> <span class="keyword">my</span> <span class="variable">$key</span> <span class="operator">(</span><span class="keyword">keys</span> <span class="variable">%hash</span><span class="operator">)</span> <span class="operator">{</span>
<span class="keyword">print</span> <span class="string">"$key => $hash{$key}\n"</span><span class="operator">;</span>
<span class="operator">}</span>
</pre>
<p>And then replace the hash name with the reference:</p>
<pre>
<span class="keyword">for</span> <span class="keyword">my</span> <span class="variable">$key</span> <span class="operator">(</span><span class="keyword">keys</span> <span class="variable">%</span><span class="operator">{</span><span class="variable">$href</span><span class="operator">}</span><span class="operator">)</span> <span class="operator">{</span>
<span class="keyword">print</span> <span class="string">"$key => ${$href}{$key}\n"</span><span class="operator">;</span>
<span class="operator">}</span>
</pre>
<p>
</p>
<h3><a name="use_rule_2"><strong>Use Rule 2</strong></a></h3>
<p><strong>Use Rule 1</strong> is all you really need, because it tells you how to do
absolutely everything you ever need to do with references. But the
most common thing to do with an array or a hash is to extract a single
element, and the <strong>Use Rule 1</strong> notation is cumbersome. So there is an
abbreviation.</p>
<p><code>${$aref}[3]</code> is too hard to read, so you can write <code>$aref->[3]</code>
instead.</p>
<p><code>${$href}{red}</code> is too hard to read, so you can write
<code>$href->{red}</code> instead.</p>
<p>If <code>$aref</code> holds a reference to an array, then <code>$aref->[3]</code> is
the fourth element of the array. Don't confuse this with <code>$aref[3]</code>,
which is the fourth element of a totally different array, one
deceptively named <code>@aref</code>. <code>$aref</code> and <code>@aref</code> are unrelated the
same way that <code>$item</code> and <code>@item</code> are.</p>
<p>Similarly, <code>$href->{'red'}</code> is part of the hash referred to by
the scalar variable <code>$href</code>, perhaps even one with no name.
<code>$href{'red'}</code> is part of the deceptively named <code>%href</code> hash. It's
easy to forget to leave out the <code>-></code>, and if you do, you'll get
bizarre results when your program gets array and hash elements out of
totally unexpected hashes and arrays that weren't the ones you wanted
to use.</p>
<p>
</p>
<h2><a name="an_example">An Example</a></h2>
<p>Let's see a quick example of how all this is useful.</p>
<p>First, remember that <code>[1, 2, 3]</code> makes an anonymous array containing
<code>(1, 2, 3)</code>, and gives you a reference to that array.</p>
<p>Now think about</p>
<pre>
<span class="variable">@a</span> <span class="operator">=</span> <span class="operator">(</span> <span class="operator">[</span><span class="number">1</span><span class="operator">,</span> <span class="number">2</span><span class="operator">,</span> <span class="number">3</span><span class="operator">]</span><span class="operator">,</span>
<span class="operator">[</span><span class="number">4</span><span class="operator">,</span> <span class="number">5</span><span class="operator">,</span> <span class="number">6</span><span class="operator">]</span><span class="operator">,</span>
<span class="operator">[</span><span class="number">7</span><span class="operator">,</span> <span class="number">8</span><span class="operator">,</span> <span class="number">9</span><span class="operator">]</span>
<span class="operator">);</span>
</pre>
<p>@a is an array with three elements, and each one is a reference to
another array.</p>
<p><code>$a[1]</code> is one of these references. It refers to an array, the array
containing <code>(4, 5, 6)</code>, and because it is a reference to an array,
<strong>Use Rule 2</strong> says that we can write <code>$a[1]->[2]</code> to get the
third element from that array. <code>$a[1]->[2]</code> is the 6.
Similarly, <code>$a[0]->[1]</code> is the 2. What we have here is like a
two-dimensional array; you can write <code>$a[ROW]->[COLUMN]</code> to get
or set the element in any row and any column of the array.</p>
<p>The notation still looks a little cumbersome, so there's one more
abbreviation:</p>
<p>
</p>
<h2><a name="arrow_rule">Arrow Rule</a></h2>
<p>In between two <strong>subscripts</strong>, the arrow is optional.</p>
<p>Instead of <code>$a[1]->[2]</code>, we can write <code>$a[1][2]</code>; it means the
same thing. Instead of <code>$a[0]->[1] = 23</code>, we can write
<code>$a[0][1] = 23</code>; it means the same thing.</p>
<p>Now it really looks like two-dimensional arrays!</p>
<p>You can see why the arrows are important. Without them, we would have
had to write <code>${$a[1]}[2]</code> instead of <code>$a[1][2]</code>. For
three-dimensional arrays, they let us write <code>$x[2][3][5]</code> instead of
the unreadable <code>${${$x[2]}[3]}[5]</code>.</p>
<p>
</p>
<hr />
<h1><a name="solution">Solution</a></h1>
<p>Here's the answer to the problem I posed earlier, of reformatting a
file of city and country names.</p>
<pre>
<span class="number">1</span> <span class="keyword">my</span> <span class="variable">%table</span><span class="operator">;</span>
</pre>
<pre>
<span class="number">2</span> <span class="keyword">while</span> <span class="operator">(<>)</span> <span class="operator">{</span>
<span class="number">3</span> <span class="keyword">chomp</span><span class="operator">;</span>
<span class="number">4</span> <span class="keyword">my</span> <span class="operator">(</span><span class="variable">$city</span><span class="operator">,</span> <span class="variable">$country</span><span class="operator">)</span> <span class="operator">=</span> <span class="keyword">split</span> <span class="regex">/, /</span><span class="operator">;</span>
<span class="number">5</span> <span class="variable">$table</span><span class="operator">{</span><span class="variable">$country</span><span class="operator">}</span> <span class="operator">=</span> <span class="operator">[]</span> <span class="keyword">unless</span> <span class="keyword">exists</span> <span class="variable">$table</span><span class="operator">{</span><span class="variable">$country</span><span class="operator">}</span><span class="operator">;</span>
<span class="number">6</span> <span class="keyword">push</span> <span class="variable">@</span><span class="operator">{</span><span class="variable">$table</span><span class="operator">{</span><span class="variable">$country</span><span class="operator">}}</span><span class="operator">,</span> <span class="variable">$city</span><span class="operator">;</span>
<span class="number">7</span> <span class="operator">}</span>
</pre>
<pre>
<span class="number">8</span> <span class="keyword">foreach</span> <span class="variable">$country</span> <span class="operator">(</span><span class="keyword">sort</span> <span class="keyword">keys</span> <span class="variable">%table</span><span class="operator">)</span> <span class="operator">{</span>
<span class="number">9</span> <span class="keyword">print</span> <span class="string">"$country: "</span><span class="operator">;</span>
<span class="number">10</span> <span class="keyword">my</span> <span class="variable">@cities</span> <span class="operator">=</span> <span class="variable">@</span><span class="operator">{</span><span class="variable">$table</span><span class="operator">{</span><span class="variable">$country</span><span class="operator">}}</span><span class="operator">;</span>
<span class="number">11</span> <span class="keyword">print</span> <span class="keyword">join</span> <span class="string">', '</span><span class="operator">,</span> <span class="keyword">sort</span> <span class="variable">@cities</span><span class="operator">;</span>
<span class="number">12</span> <span class="keyword">print</span> <span class="string">".\n"</span><span class="operator">;</span>
<span class="number">13</span> <span class="operator">}</span>
</pre>
<p>The program has two pieces: Lines 2--7 read the input and build a data
structure, and lines 8-13 analyze the data and print out the report.
We're going to have a hash, <code>%table</code>, whose keys are country names,
and whose values are references to arrays of city names. The data
structure will look like this:</p>
<pre>
%table
+-------+---+
| | | +-----------+--------+
|Germany| *---->| Frankfurt | Berlin |
| | | +-----------+--------+
+-------+---+
| | | +----------+
|Finland| *---->| Helsinki |
| | | +----------+
+-------+---+
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?