📄 perlreftut.1
字号:
\& ...\& }.Ve.PPso replace the array name, \f(CW@array\fR, with the reference:.PP.Vb 3\& for my $element (@{$aref}) {\& ...\& }.Ve.PP\&\*(L"How do I print out the contents of a hash when all I have is areference?\*(R" First write the code for printing out a hash:.PP.Vb 3\& for my $key (keys %hash) {\& print "$key => $hash{$key}\en";\& }.Ve.PPAnd then replace the hash name with the reference:.PP.Vb 3\& for my $key (keys %{$href}) {\& print "$key => ${$href}{$key}\en";\& }.Ve.PP\fI\f(BIUse Rule 2\fI\fR.IX Subsection "Use Rule 2".PP\&\fBUse Rule 1\fR is all you really need, because it tells you how to doabsolutely everything you ever need to do with references. But themost common thing to do with an array or a hash is to extract a singleelement, and the \fBUse Rule 1\fR notation is cumbersome. So there is anabbreviation..PP\&\f(CW\*(C`${$aref}[3]\*(C'\fR is too hard to read, so you can write \f(CW\*(C`$aref\->[3]\*(C'\fRinstead..PP\&\f(CW\*(C`${$href}{red}\*(C'\fR is too hard to read, so you can write\&\f(CW\*(C`$href\->{red}\*(C'\fR instead..PPIf \f(CW$aref\fR holds a reference to an array, then \f(CW\*(C`$aref\->[3]\*(C'\fR isthe fourth element of the array. Don't confuse this with \f(CW$aref[3]\fR,which is the fourth element of a totally different array, onedeceptively named \f(CW@aref\fR. \f(CW$aref\fR and \f(CW@aref\fR are unrelated thesame way that \f(CW$item\fR and \f(CW@item\fR are..PPSimilarly, \f(CW\*(C`$href\->{\*(Aqred\*(Aq}\*(C'\fR is part of the hash referred to bythe scalar variable \f(CW$href\fR, perhaps even one with no name.\&\f(CW$href{\*(Aqred\*(Aq}\fR is part of the deceptively named \f(CW%href\fR hash. It'seasy to forget to leave out the \f(CW\*(C`\->\*(C'\fR, and if you do, you'll getbizarre results when your program gets array and hash elements out oftotally unexpected hashes and arrays that weren't the ones you wantedto use..Sh "An Example".IX Subsection "An Example"Let's see a quick example of how all this is useful..PPFirst, remember that \f(CW\*(C`[1, 2, 3]\*(C'\fR makes an anonymous array containing\&\f(CW\*(C`(1, 2, 3)\*(C'\fR, and gives you a reference to that array..PPNow think about.PP.Vb 4\& @a = ( [1, 2, 3],\& [4, 5, 6],\& [7, 8, 9]\& );.Ve.PP\&\f(CW@a\fR is an array with three elements, and each one is a reference toanother array..PP\&\f(CW$a[1]\fR is one of these references. It refers to an array, the arraycontaining \f(CW\*(C`(4, 5, 6)\*(C'\fR, and because it is a reference to an array,\&\fBUse Rule 2\fR says that we can write \f(CW$a[1]\->[2]\fR to get thethird element from that array. \f(CW$a[1]\->[2]\fR is the 6.Similarly, \f(CW$a[0]\->[1]\fR is the 2. What we have here is like atwo-dimensional array; you can write \f(CW$a[ROW]\->[COLUMN]\fR to getor set the element in any row and any column of the array..PPThe notation still looks a little cumbersome, so there's one moreabbreviation:.Sh "Arrow Rule".IX Subsection "Arrow Rule"In between two \fBsubscripts\fR, the arrow is optional..PPInstead of \f(CW$a[1]\->[2]\fR, we can write \f(CW$a[1][2]\fR; it means thesame thing. Instead of \f(CW\*(C`$a[0]\->[1] = 23\*(C'\fR, we can write\&\f(CW\*(C`$a[0][1] = 23\*(C'\fR; it means the same thing..PPNow it really looks like two-dimensional arrays!.PPYou can see why the arrows are important. Without them, we would havehad to write \f(CW\*(C`${$a[1]}[2]\*(C'\fR instead of \f(CW$a[1][2]\fR. Forthree-dimensional arrays, they let us write \f(CW$x[2][3][5]\fR instead ofthe unreadable \f(CW\*(C`${${$x[2]}[3]}[5]\*(C'\fR..SH "Solution".IX Header "Solution"Here's the answer to the problem I posed earlier, of reformatting afile of city and country names..PP.Vb 1\& 1 my %table;\&\& 2 while (<>) {\& 3 chomp;\& 4 my ($city, $country) = split /, /;\& 5 $table{$country} = [] unless exists $table{$country};\& 6 push @{$table{$country}}, $city;\& 7 }\&\& 8 foreach $country (sort keys %table) {\& 9 print "$country: ";\& 10 my @cities = @{$table{$country}};\& 11 print join \*(Aq, \*(Aq, sort @cities;\& 12 print ".\en";\& 13 }.Ve.PPThe program has two pieces: Lines 2\-\-7 read the input and build a datastructure, and lines 8\-13 analyze the data and print out the report.We're going to have a hash, \f(CW%table\fR, whose keys are country names,and whose values are references to arrays of city names. The datastructure will look like this:.PP.Vb 10\& %table\& +\-\-\-\-\-\-\-+\-\-\-+\& | | | +\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-+\& |Germany| *\-\-\-\->| Frankfurt | Berlin |\& | | | +\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-+\& +\-\-\-\-\-\-\-+\-\-\-+\& | | | +\-\-\-\-\-\-\-\-\-\-+\& |Finland| *\-\-\-\->| Helsinki |\& | | | +\-\-\-\-\-\-\-\-\-\-+\& +\-\-\-\-\-\-\-+\-\-\-+\& | | | +\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-+\& | USA | *\-\-\-\->| Chicago | Washington | New York |\& | | | +\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-+\& +\-\-\-\-\-\-\-+\-\-\-+.Ve.PPWe'll look at output first. Supposing we already have this structure,how do we print it out?.PP.Vb 6\& 8 foreach $country (sort keys %table) {\& 9 print "$country: ";\& 10 my @cities = @{$table{$country}};\& 11 print join \*(Aq, \*(Aq, sort @cities;\& 12 print ".\en";\& 13 }.Ve.PP\&\f(CW%table\fR is anordinary hash, and we get a list of keys from it, sort the keys, andloop over the keys as usual. The only use of references is in line 10.\&\f(CW$table{$country}\fR looks up the key \f(CW$country\fR in the hashand gets the value, which is a reference to an array of cities in that country.\&\fBUse Rule 1\fR says thatwe can recover the array by saying\&\f(CW\*(C`@{$table{$country}}\*(C'\fR. Line 10 is just like.PP.Vb 1\& @cities = @array;.Ve.PPexcept that the name \f(CW\*(C`array\*(C'\fR has been replaced by the reference\&\f(CW\*(C`{$table{$country}}\*(C'\fR. The \f(CW\*(C`@\*(C'\fR tells Perl to get the entire array.Having gotten the list of cities, we sort it, join it, and print itout as usual..PPLines 2\-7 are responsible for building the structure in the firstplace. Here they are again:.PP.Vb 6\& 2 while (<>) {\& 3 chomp;\& 4 my ($city, $country) = split /, /;\& 5 $table{$country} = [] unless exists $table{$country};\& 6 push @{$table{$country}}, $city;\& 7 }.Ve.PPLines 2\-4 acquire a city and country name. Line 5 looks to see if thecountry is already present as a key in the hash. If it's not, theprogram uses the \f(CW\*(C`[]\*(C'\fR notation (\fBMake Rule 2\fR) to manufacture a new,empty anonymous array of cities, and installs a reference to it intothe hash under the appropriate key..PPLine 6 installs the city name into the appropriate array.\&\f(CW$table{$country}\fR now holds a reference to the array of cities seenin that country so far. Line 6 is exactly like.PP.Vb 1\& push @array, $city;.Ve.PPexcept that the name \f(CW\*(C`array\*(C'\fR has been replaced by the reference\&\f(CW\*(C`{$table{$country}}\*(C'\fR. The \f(CW\*(C`push\*(C'\fR adds a city name to the end of thereferred-to array..PPThere's one fine point I skipped. Line 5 is unnecessary, and we canget rid of it..PP.Vb 6\& 2 while (<>) {\& 3 chomp;\& 4 my ($city, $country) = split /, /;\& 5 #### $table{$country} = [] unless exists $table{$country};\& 6 push @{$table{$country}}, $city;\& 7 }.Ve.PPIf there's already an entry in \f(CW%table\fR for the current \f(CW$country\fR,then nothing is different. Line 6 will locate the value in\&\f(CW$table{$country}\fR, which is a reference to an array, and push\&\f(CW$city\fR into the array. Butwhat does it do when\&\f(CW$country\fR holds a key, say \f(CW\*(C`Greece\*(C'\fR, that is not yet in \f(CW%table\fR?.PPThis is Perl, so it does the exact right thing. It sees that you wantto push \f(CW\*(C`Athens\*(C'\fR onto an array that doesn't exist, so it helpfullymakes a new, empty, anonymous array for you, installs it into\&\f(CW%table\fR, and then pushes \f(CW\*(C`Athens\*(C'\fR onto it. This is called`autovivification'\-\-bringing things to life automatically. Perl sawthat they key wasn't in the hash, so it created a new hash entryautomatically. Perl saw that you wanted to use the hash value as anarray, so it created a new empty array and installed a reference to itin the hash automatically. And as usual, Perl made the array oneelement longer to hold the new city name..SH "The Rest".IX Header "The Rest"I promised to give you 90% of the benefit with 10% of the details, andthat means I left out 90% of the details. Now that you have anoverview of the important parts, it should be easier to read theperlref manual page, which discusses 100% of the details..PPSome of the highlights of perlref:.IP "\(bu" 4You can make references to anything, including scalars, functions, andother references..IP "\(bu" 4In \fBUse Rule 1\fR, you can omit the curly brackets whenever the thinginside them is an atomic scalar variable like \f(CW$aref\fR. For example,\&\f(CW@$aref\fR is the same as \f(CW\*(C`@{$aref}\*(C'\fR, and \f(CW$$aref[1]\fR is the same as\&\f(CW\*(C`${$aref}[1]\*(C'\fR. If you're just starting out, you may want to adoptthe habit of always including the curly brackets..IP "\(bu" 4This doesn't copy the underlying array:.Sp.Vb 1\& $aref2 = $aref1;.Ve.SpYou get two references to the same array. If you modify\&\f(CW\*(C`$aref1\->[23]\*(C'\fR and then look at\&\f(CW\*(C`$aref2\->[23]\*(C'\fR you'll see the change..SpTo copy the array, use.Sp.Vb 1\& $aref2 = [@{$aref1}];.Ve.SpThis uses \f(CW\*(C`[...]\*(C'\fR notation to create a new anonymous array, and\&\f(CW$aref2\fR is assigned a reference to the new array. The new array isinitialized with the contents of the array referred to by \f(CW$aref1\fR..SpSimilarly, to copy an anonymous hash, you can use.Sp.Vb 1\& $href2 = {%{$href1}};.Ve.IP "\(bu" 4To see if a variable contains a reference, use the \f(CW\*(C`ref\*(C'\fR function. Itreturns true if its argument is a reference. Actually it's a littlebetter than that: It returns \f(CW\*(C`HASH\*(C'\fR for hash references and \f(CW\*(C`ARRAY\*(C'\fRfor array references..IP "\(bu" 4If you try to use a reference like a string, you get strings like.Sp.Vb 1\& ARRAY(0x80f5dec) or HASH(0x826afc0).Ve.SpIf you ever see a string that looks like this, you'll know youprinted out a reference by mistake..SpA side effect of this representation is that you can use \f(CW\*(C`eq\*(C'\fR to seeif two references refer to the same thing. (But you should usually use\&\f(CW\*(C`==\*(C'\fR instead because it's much faster.).IP "\(bu" 4You can use a string as if it were a reference. If you use the string\&\f(CW"foo"\fR as an array reference, it's taken to be a reference to thearray \f(CW@foo\fR. This is called a \fIsoft reference\fR or \fIsymbolicreference\fR. The declaration \f(CW\*(C`use strict \*(Aqrefs\*(Aq\*(C'\fR disables thisfeature, which can cause all sorts of trouble if you use it by accident..PPYou might prefer to go on to perllol instead of perlref; itdiscusses lists of lists and multidimensional arrays in detail. Afterthat, you should move on to perldsc; it's a Data Structure Cookbookthat shows recipes for using and printing out arrays of hashes, hashesof arrays, and other kinds of data..SH "Summary".IX Header "Summary"Everyone needs compound data structures, and in Perl the way you getthem is with references. There are four important rules for managingreferences: Two for making references and two for using them. Onceyou know these rules you can do most of the important things you needto do with references..SH "Credits".IX Header "Credits"Author: Mark Jason Dominus, Plover Systems (\f(CW\*(C`mjd\-perl\-ref+@plover.com\*(C'\fR).PPThis article originally appeared in \fIThe Perl Journal\fR( http://www.tpj.com/ ) volume 3, #2. Reprinted with permission..PPThe original title was \fIUnderstand References Today\fR..Sh "Distribution Conditions".IX Subsection "Distribution Conditions"Copyright 1998 The Perl Journal..PPThis documentation is free; you can redistribute it and/or modify itunder the same terms as Perl itself..PPIrrespective of its distribution, all code examples in these files arehereby placed into the public domain. You are permitted andencouraged to use this code in your own programs for fun or for profitas you see fit. A simple comment in the code giving credit would becourteous but is not required.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -