📄 perldata.1
字号:
.PPA list value may also be subscripted like a normal array. You mustput the list in parentheses to avoid ambiguity. For example:.PP.Vb 2\& # Stat returns list value.\& $time = (stat($file))[8];\&\& # SYNTAX ERROR HERE.\& $time = stat($file)[8]; # OOPS, FORGOT PARENTHESES\&\& # Find a hex digit.\& $hexdigit = (\*(Aqa\*(Aq,\*(Aqb\*(Aq,\*(Aqc\*(Aq,\*(Aqd\*(Aq,\*(Aqe\*(Aq,\*(Aqf\*(Aq)[$digit\-10];\&\& # A "reverse comma operator".\& return (pop(@foo),pop(@foo))[0];.Ve.PPLists may be assigned to only when each element of the listis itself legal to assign to:.PP.Vb 1\& ($a, $b, $c) = (1, 2, 3);\&\& ($map{\*(Aqred\*(Aq}, $map{\*(Aqblue\*(Aq}, $map{\*(Aqgreen\*(Aq}) = (0x00f, 0x0f0, 0xf00);.Ve.PPAn exception to this is that you may assign to \f(CW\*(C`undef\*(C'\fR in a list.This is useful for throwing away some of the return values of afunction:.PP.Vb 1\& ($dev, $ino, undef, undef, $uid, $gid) = stat($file);.Ve.PPList assignment in scalar context returns the number of elementsproduced by the expression on the right side of the assignment:.PP.Vb 2\& $x = (($foo,$bar) = (3,2,1)); # set $x to 3, not 2\& $x = (($foo,$bar) = f()); # set $x to f()\*(Aqs return count.Ve.PPThis is handy when you want to do a list assignment in a Booleancontext, because most list functions return a null list when finished,which when assigned produces a 0, which is interpreted as \s-1FALSE\s0..PPIt's also the source of a useful idiom for executing a function orperforming an operation in list context and then counting the number ofreturn values, by assigning to an empty list and then using thatassignment in scalar context. For example, this code:.PP.Vb 1\& $count = () = $string =~ /\ed+/g;.Ve.PPwill place into \f(CW$count\fR the number of digit groups found in \f(CW$string\fR.This happens because the pattern match is in list context (since itis being assigned to the empty list), and will therefore return a listof all matching parts of the string. The list assignment in scalarcontext will translate that into the number of elements (here, thenumber of times the pattern matched) and assign that to \f(CW$count\fR. Notethat simply using.PP.Vb 1\& $count = $string =~ /\ed+/g;.Ve.PPwould not have worked, since a pattern match in scalar context willonly return true or false, rather than a count of matches..PPThe final element of a list assignment may be an array or a hash:.PP.Vb 2\& ($a, $b, @rest) = split;\& my($a, $b, %rest) = @_;.Ve.PPYou can actually put an array or hash anywhere in the list, but the first onein the list will soak up all the values, and anything after it will becomeundefined. This may be useful in a \fImy()\fR or \fIlocal()\fR..PPA hash can be initialized using a literal list holding pairs ofitems to be interpreted as a key and a value:.PP.Vb 2\& # same as map assignment above\& %map = (\*(Aqred\*(Aq,0x00f,\*(Aqblue\*(Aq,0x0f0,\*(Aqgreen\*(Aq,0xf00);.Ve.PPWhile literal lists and named arrays are often interchangeable, that'snot the case for hashes. Just because you can subscript a list value likea normal array does not mean that you can subscript a list value as ahash. Likewise, hashes included as parts of other lists (includingparameters lists and return lists from functions) always flatten out intokey/value pairs. That's why it's good to use references sometimes..PPIt is often more readable to use the \f(CW\*(C`=>\*(C'\fR operator between key/valuepairs. The \f(CW\*(C`=>\*(C'\fR operator is mostly just a more visually distinctivesynonym for a comma, but it also arranges for its left-hand operand to beinterpreted as a string \*(-- if it's a bareword that would be a legal simpleidentifier (\f(CW\*(C`=>\*(C'\fR doesn't quote compound identifiers, that containdouble colons). This makes it nice for initializing hashes:.PP.Vb 5\& %map = (\& red => 0x00f,\& blue => 0x0f0,\& green => 0xf00,\& );.Ve.PPor for initializing hash references to be used as records:.PP.Vb 5\& $rec = {\& witch => \*(AqMable the Merciless\*(Aq,\& cat => \*(AqFluffy the Ferocious\*(Aq,\& date => \*(Aq10/31/1776\*(Aq,\& };.Ve.PPor for using call-by-named-parameter to complicated functions:.PP.Vb 7\& $field = $query\->radio_group(\& name => \*(Aqgroup_name\*(Aq,\& values => [\*(Aqeenie\*(Aq,\*(Aqmeenie\*(Aq,\*(Aqminie\*(Aq],\& default => \*(Aqmeenie\*(Aq,\& linebreak => \*(Aqtrue\*(Aq,\& labels => \e%labels\& );.Ve.PPNote that just because a hash is initialized in that order doesn'tmean that it comes out in that order. See \*(L"sort\*(R" in perlfunc for examplesof how to arrange for an output ordering..Sh "Subscripts".IX Subsection "Subscripts"An array is subscripted by specifying a dollar sign (\f(CW\*(C`$\*(C'\fR), then thename of the array (without the leading \f(CW\*(C`@\*(C'\fR), then the subscript insidesquare brackets. For example:.PP.Vb 2\& @myarray = (5, 50, 500, 5000);\& print "Element Number 2 is", $myarray[2], "\en";.Ve.PPThe array indices start with 0. A negative subscript retrieves its value from the end. In our example, \f(CW$myarray[\-1]\fR would have been 5000, and \f(CW$myarray[\-2]\fR would have been 500..PPHash subscripts are similar, only instead of square brackets curly bracketsare used. For example:.PP.Vb 7\& %scientists = \& (\& "Newton" => "Isaac",\& "Einstein" => "Albert",\& "Darwin" => "Charles",\& "Feynman" => "Richard",\& );\&\& print "Darwin\*(Aqs First Name is ", $scientists{"Darwin"}, "\en";.Ve.Sh "Slices".IX Xref "slice array, slice hash, slice".IX Subsection "Slices"A common way to access an array or a hash is one scalar element at atime. You can also subscript a list to get a single element from it..PP.Vb 3\& $whoami = $ENV{"USER"}; # one element from the hash\& $parent = $ISA[0]; # one element from the array\& $dir = (getpwnam("daemon"))[7]; # likewise, but with list.Ve.PPA slice accesses several elements of a list, an array, or a hashsimultaneously using a list of subscripts. It's more convenientthan writing out the individual elements as a list of separatescalar values..PP.Vb 4\& ($him, $her) = @folks[0,\-1]; # array slice\& @them = @folks[0 .. 3]; # array slice\& ($who, $home) = @ENV{"USER", "HOME"}; # hash slice\& ($uid, $dir) = (getpwnam("daemon"))[2,7]; # list slice.Ve.PPSince you can assign to a list of variables, you can also assign toan array or hash slice..PP.Vb 4\& @days[3..5] = qw/Wed Thu Fri/;\& @colors{\*(Aqred\*(Aq,\*(Aqblue\*(Aq,\*(Aqgreen\*(Aq} \& = (0xff0000, 0x0000ff, 0x00ff00);\& @folks[0, \-1] = @folks[\-1, 0];.Ve.PPThe previous assignments are exactly equivalent to.PP.Vb 4\& ($days[3], $days[4], $days[5]) = qw/Wed Thu Fri/;\& ($colors{\*(Aqred\*(Aq}, $colors{\*(Aqblue\*(Aq}, $colors{\*(Aqgreen\*(Aq})\& = (0xff0000, 0x0000ff, 0x00ff00);\& ($folks[0], $folks[\-1]) = ($folks[\-1], $folks[0]);.Ve.PPSince changing a slice changes the original array or hash that it'sslicing, a \f(CW\*(C`foreach\*(C'\fR construct will alter some\*(--or even all\*(--of thevalues of the array or hash..PP.Vb 1\& foreach (@array[ 4 .. 10 ]) { s/peter/paul/ } \&\& foreach (@hash{qw[key1 key2]}) {\& s/^\es+//; # trim leading whitespace\& s/\es+$//; # trim trailing whitespace\& s/(\ew+)/\eu\eL$1/g; # "titlecase" words\& }.Ve.PPA slice of an empty list is still an empty list. Thus:.PP.Vb 3\& @a = ()[1,0]; # @a has no elements\& @b = (@a)[0,1]; # @b has no elements\& @c = (0,1)[2,3]; # @c has no elements.Ve.PPBut:.PP.Vb 2\& @a = (1)[1,0]; # @a has two elements\& @b = (1,undef)[1,0,2]; # @b has three elements.Ve.PPThis makes it easy to write loops that terminate when a null listis returned:.PP.Vb 3\& while ( ($home, $user) = (getpwent)[7,0]) {\& printf "%\-8s %s\en", $user, $home;\& }.Ve.PPAs noted earlier in this document, the scalar sense of list assignmentis the number of elements on the right-hand side of the assignment.The null list contains no elements, so when the password file isexhausted, the result is 0, not 2..PPIf you're confused about why you use an '@' there on a hash sliceinstead of a '%', think of it like this. The type of bracket (squareor curly) governs whether it's an array or a hash being looked at.On the other hand, the leading symbol ('$' or '@') on the array orhash indicates whether you are getting back a singular value (ascalar) or a plural one (a list)..Sh "Typeglobs and Filehandles".IX Xref "typeglob filehandle *".IX Subsection "Typeglobs and Filehandles"Perl uses an internal type called a \fItypeglob\fR to hold an entiresymbol table entry. The type prefix of a typeglob is a \f(CW\*(C`*\*(C'\fR, becauseit represents all types. This used to be the preferred way topass arrays and hashes by reference into a function, but now thatwe have real references, this is seldom needed..PPThe main use of typeglobs in modern Perl is create symbol table aliases.This assignment:.PP.Vb 1\& *this = *that;.Ve.PPmakes \f(CW$this\fR an alias for \f(CW$that\fR, \f(CW@this\fR an alias for \f(CW@that\fR, \f(CW%this\fR an aliasfor \f(CW%that\fR, &this an alias for &that, etc. Much safer is to use a reference.This:.PP.Vb 1\& local *Here::blue = \e$There::green;.Ve.PPtemporarily makes \f(CW$Here::blue\fR an alias for \f(CW$There::green\fR, but doesn'tmake \f(CW@Here::blue\fR an alias for \f(CW@There::green\fR, or \f(CW%Here::blue\fR an alias for\&\f(CW%There::green\fR, etc. See \*(L"Symbol Tables\*(R" in perlmod for more examplesof this. Strange though this may seem, this is the basis for the wholemodule import/export system..PPAnother use for typeglobs is to pass filehandles into a function orto create new filehandles. If you need to use a typeglob to save awaya filehandle, do it this way:.PP.Vb 1\& $fh = *STDOUT;.Ve.PPor perhaps as a real reference, like this:.PP.Vb 1\& $fh = \e*STDOUT;.Ve.PPSee perlsub for examples of using these as indirect filehandlesin functions..PPTypeglobs are also a way to create a local filehandle using the \fIlocal()\fRoperator. These last until their block is exited, but may be passed back.For example:.PP.Vb 7\& sub newopen {\& my $path = shift;\& local *FH; # not my!\& open (FH, $path) or return undef;\& return *FH;\& }\& $fh = newopen(\*(Aq/etc/passwd\*(Aq);.Ve.PPNow that we have the \f(CW*foo{THING}\fR notation, typeglobs aren't used as muchfor filehandle manipulations, although they're still needed to pass brandnew file and directory handles into or out of functions. That's because\&\f(CW*HANDLE{IO}\fR only works if \s-1HANDLE\s0 has already been used as a handle.In other words, \f(CW*FH\fR must be used to create new symbol table entries;\&\f(CW*foo{THING}\fR cannot. When in doubt, use \f(CW*FH\fR..PPAll functions that are capable of creating filehandles (\fIopen()\fR,\&\fIopendir()\fR, \fIpipe()\fR, \fIsocketpair()\fR, \fIsysopen()\fR, \fIsocket()\fR, and \fIaccept()\fR)automatically create an anonymous filehandle if the handle passed tothem is an uninitialized scalar variable. This allows the constructssuch as \f(CW\*(C`open(my $fh, ...)\*(C'\fR and \f(CW\*(C`open(local $fh,...)\*(C'\fR to be used tocreate filehandles that will conveniently be closed automatically whenthe scope ends, provided there are no other references to them. Thislargely eliminates the need for typeglobs when opening filehandlesthat must be passed around, as in the following example:.PP.Vb 5\& sub myopen {\& open my $fh, "@_"\& or die "Can\*(Aqt open \*(Aq@_\*(Aq: $!";\& return $fh;\& }\&\& {\& my $f = myopen("</etc/motd");\& print <$f>;\& # $f implicitly closed here\& }.Ve.PPNote that if an initialized scalar variable is used instead theresult is different: \f(CW\*(C`my $fh=\*(Aqzzz\*(Aq; open($fh, ...)\*(C'\fR is equivalentto \f(CW\*(C`open( *{\*(Aqzzz\*(Aq}, ...)\*(C'\fR.\&\f(CW\*(C`use strict \*(Aqrefs\*(Aq\*(C'\fR forbids such practice..PPAnother way to create anonymous filehandles is with the Symbolmodule or with the IO::Handle module and its ilk. These moduleshave the advantage of not hiding different types of the same nameduring the \fIlocal()\fR. See the bottom of \*(L"\fIopen()\fR\*(R" in perlfunc for anexample..SH "SEE ALSO".IX Header "SEE ALSO"See perlvar for a description of Perl's built-in variables anda discussion of legal variable names. See perlref, perlsub,and \*(L"Symbol Tables\*(R" in perlmod for more discussion on typeglobs andthe \f(CW*foo{THING}\fR syntax.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -