ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП |
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы. |
2.5 OperatorsThe terms of an expression often need to be combined and modified in various ways, and that's what operators are for. The tightness with which operators bind is controlled by the precedence of the operators. Perl operators have the following associativity and precedence, listed from highest precedence to lowest.[27]
It may seem like there are too many precedence levels. Well, you're right, there are. Fortunately, there are two things going for you here. First, the precedence levels as they're defined usually follow your intuition, presuming you're not psychotic. And second, if you're merely neurotic, you can always put in extra parentheses to relieve your anxiety. Note that any operators borrowed from C keep the same precedence relationship with each other, even where C's precedence is slightly screwy. (This makes learning Perl easier for C folks.) In the following sections, these operators are covered in precedence order. With very few exceptions, these all operate on scalar values only, not list values. We'll mention the exceptions as they come up. 2.5.1 Terms and List Operators (Leftward)Any term is of highest precedence in Perl. These include variables, quote and quotelike operators, any expression in parentheses, and any function whose arguments are parenthesized. Actually, there aren't really any functions in this sense, just list operators and unary operators behaving as functions because you put parentheses around their arguments. These operators are all covered in Chapter 3. Now, listen carefully. Here are a couple of rules that are very important and simplify things greatly, but may occasionally produce counterintuitive results for the unwary. If any list operator (such as print) or any named unary operator (such as chdir) is followed by a left parenthesis as the next token on the same line,[28] the operator and its arguments within parentheses are taken to be of highest precedence, just like a normal function call. The rule is: If it looks like a function call, it is a function call. You can make it look like a non-function by prefixing the arguments with a unary plus, which does absolutely nothing, semantically speaking - it doesn't even convert the argument to numeric.
For example, since || has lower precedence than chdir, we get: chdir $foo || die; # (chdir $foo) || die chdir($foo) || die; # (chdir $foo) || die chdir ($foo) || die; # (chdir $foo) || die chdir +($foo) || die; # (chdir $foo) || die but, because chdir $foo * 20; # chdir ($foo * 20) chdir($foo) * 20; # (chdir $foo) * 20 chdir ($foo) * 20; # (chdir $foo) * 20 chdir +($foo) * 20; # chdir ($foo * 20) Likewise for numeric operators: rand 10 * 20; # rand (10 * 20) rand(10) * 20; # (rand 10) * 20 rand (10) * 20; # (rand 10) * 20 rand +(10) * 20; # rand (10 * 20) In the absence of parentheses, the precedence of list operators such as print, sort, or chmod is either very high or very low depending on whether you look at the left side of the operator or the right side of it. (That's what the "Leftward" is doing in the title of this section.) For example, in: @ary = (1, 3, sort 4, 2); print @ary; # prints 1324 the commas on the right of the sort are evaluated before the sort, but the commas on the left are evaluated after. In other words, a list operator tends to gobble up all the arguments that follow it, and then act like a simple term with regard to the preceding expression. Note that you have to be careful with parentheses: # These evaluate exit before doing the print: print($foo, exit); # Obviously not what you want. print $foo, exit; # Nor is this. # These do the print before evaluating exit: (print $foo), exit; # This is what you want. print($foo), exit; # Or this. print ($foo), exit; # Or even this. Also note that: print ($foo & 255) + 1, "\n"; # prints ($foo & 255) probably doesn't do what you expect at first glance. Fortunately,
mistakes of this nature generally produce warnings like " Also parsed as terms are the 2.5.2 The Arrow OperatorJust as in C and C++, Otherwise, the right side must be a method name or a simple scalar variable containing the method name, and the value of the left side must either be an object (a blessed reference) or a class name (that is, a package name). See Chapter 5. 2.5.3 Autoincrement and AutodecrementThe
The autoincrement operator has a little extra built-in magic to it. If
you increment a variable that is numeric, or that has ever been used in
a numeric context, you get a normal increment. If, however, the
variable has only been used in string contexts since it was set, and
has a value that is not null and matches the pattern
print ++($foo = '99'); # prints '100' print ++($foo = 'a0'); # prints 'a1' print ++($foo = 'Az'); # prints 'Ba' print ++($foo = 'zz'); # prints 'aaa' The autodecrement operator, however, is not magical. 2.5.4 ExponentiationBinary 2.5.5 Ideographic Unary OperatorsMost unary operators just have names (see "Named Unary and File Test Operators" below), but some operators are deemed important enough to merit their own special symbolic representation. Most of these operators seem to have something to do with negation. Blame the mathematicians. Unary ! performs logical negation, that is, "not". See also not
for a lower precedence version of this. The value of a negated
operation is 1 if the operand is false (numeric 0, string Unary Unary (What you perhaps didn't know is that if the argument to Unary Unary The 2.5.6 Binding OperatorsBinary Binary $string !~ /pattern/ not $string =~ /pattern/ We said that the return value indicates success, but there are many kinds of success. Substitutions return the number of successful substitutions, as do translations. (In fact, the translation operator is often used to count characters.) Since any non-zero result is true, it all works out. The most spectacular kind of true value is a list value: in a list context, pattern matches can return substrings matched by the parentheses in the pattern. But again, according to the rules of list assignment, the list assignment itself will return true if anything matched and was assigned, and false otherwise. So you sometimes see things like: if ( ($k,$v) = $string =~ m/(\w+)=(\w*)/ ) { print "KEY $k VALUE $v\n"; } Let's pick that apart. The 2.5.7 Multiplicative OperatorsPerl provides the C-like operators The Binary x is the repetition operator. In scalar context, it returns a concatenated string consisting of the left operand repeated the number of times specified by the right operand. print '-' x 80; # print row of dashes print "\t" x ($tab/8), ' ' x ($tab%8); # tab over In list context, if the left operand is a list in parentheses, the x works as a list replicator rather than a string replicator. This is useful for initializing all the elements of an array of indeterminate length to the same value: @ones = (1) x 80; # a list of 80 1's @ones = (5) x @ones; # set all elements to 5 Similarly, you can also use x to initialize array and hash slices: @keys = qw(perls before swine); @hash{@keys} = ("") x @keys; If this mystifies you, note that $hash{perls} = ""; $hash{before} = ""; $hash{swine} = ""; 2.5.8 Additive OperatorsStrangely enough, Perl also has the customary Additionally, Perl provides a string concatenation operator " $almost = "Fred" . "Flintstone"; # returns FredFlintstone Note that Perl does not place a space between the strings being concatenated. If you want the space, or if you have more than two strings to concatenate, you can use the join operator, described in Chapter 3. Most often, though, people do their concatenation implicitly inside a double-quoted string: $fullname = "$firstname $lastname"; 2.5.9 Shift OperatorsThe bit-shift operators ( 1 << 4; # returns 16 32 >> 4; # returns 2 2.5.10 Named Unary and File Test OperatorsSome of "functions" described in Chapter 3 are really unary operators, including:
These are all unary operators, with a higher precedence than some of the other binary operators. For example: sleep 4 | 3; does not sleep for 7 seconds; it sleeps for 4 seconds, and then takes the return value of sleep (typically zero) and ORs that with 3, as if the expression were parenthesized as: (sleep 4) | 3; Compare this with: print 4 | 3; which does take the value of 4 ORed with 3 before printing it (7 in this case), as if it were written: print (4 | 3); This is because print is a list operator, not a simple unary operator. Once you've learned which operators are list operators, you'll have no trouble telling them apart. When in doubt, you can always use parentheses to turn a named unary operator into a function. Remember, if it looks like a function, it is a function. Another funny thing about named unary operators is that many of them default to $_ if you don't supply an argument. However, if the thing following the named unary operator looks like it might be the start of an argument, Perl will get confused. When the next character in your program is one of the following characters, the Perl tokener returns different token types depending on whether a term or operator is expected:
So a typical boo-boo is: next if length < 80; in which the next if length() < 80; next if (length) < 80; next if 80 > length; next unless length >= 80; A file test operator is a unary operator that takes one argument, either a
filename or a filehandle, and tests the associated file to see if something
is true about it. If the argument is omitted, it tests $_, except for
The interpretation of the file permission operators
while (<>) { chomp; next unless -f $_; # ignore "special" files ... } Note that The next unless -f $file && -T _; If any of the file tests (or either the stat or lstat operators)
are given the special filehandle consisting of a solitary underline,
then the stat structure of the previous file test (or stat operator) is
used, thereby saving a system call. (This doesn't work with print "Can do.\n" if -r $a || -w _ || -x _; stat($filename); print "Readable\n" if -r _; print "Writable\n" if -w _; print "Executable\n" if -x _; print "Setuid\n" if -u _; print "Setgid\n" if -g _; print "Sticky\n" if -k _; print "Text\n" if -T _; print "Binary\n" if -B _; File ages for next unless -M $file > .5; # files older than 12 hours &newfile if -M $file < 0; # file is newer than process &mailwarning if int(-A) == 90; # file ($_) accessed 90 days ago today To reset the script's start time to the current time, change $^T as follows: $^T = time; 2.5.11 Relational OperatorsPerl has two classes of relational operators. One class operates on numeric values, and the other class operates on string values. To repeat the table given in the overview:
These operators return 2.5.12 Equality OperatorsThe equality operators are much like the relational operators.
The equal and not-equal operators return 1 for true, and For reasons that are apparent to anyone who has seen Star Wars, the 2.5.13 Bitwise OperatorsLike C, Perl has bitwise AND, OR, and XOR (exclusive
OR) operators: If both operands are strings (and have not been used as numbers since being set), these operators do bitwise operations between corresponding bits from the two strings. In this case, there's no arbitrary limit, since strings aren't arbitrarily limited in size. If one string is longer than the other, the shorter string is considered to have a sufficient number of 0 bits on the end to make up the difference. For example, if you AND together two strings: "123.45" & "234.56" you get another string: "020.44" But if you AND together a string and a number: "123.45" & 234.56 The string is first converted to a number, giving: 123.45 & 234.56 The numbers are then converted to integer: 123 & 234 which evaluates to 106. Note that all bit strings are true
(unless they come out to being the string " if ( "fred" & "\1\2\3\4" ) { ... } would need to be written instead as: if ( ("fred" & "\1\2\3\4") =~ /[^\0]/ ) { ... } 2.5.14 C-style Logical (Short Circuit) OperatorsLike C, Perl provides the
Such short circuits are not only time savers, but are frequently used to control the flow of evaluation. For example, an oft-appearing idiom in Perl programs is: open(FILE, "somefile") || die "Cannot open somefile: $!\n"; In this case, Perl first evaluates the open function. If the value is true (because somefile was successfully opened), the execution of the die function is unnecessary, and is skipped. You can read this literally as "Open some file or die!" The $home = $ENV{HOME} || $ENV{LOGDIR} || (getpwuid($<))[7] || die "You're homeless!\n"; Perl also provides lower precedence and and or operators that are more readable and don't force you to use parentheses as much. They also short-circuit. 2.5.15 Range OperatorThe
In a scalar context, The precedence is a little lower than As a scalar operator: if (101 .. 200) { print; } # print 2nd hundred lines next line if (1 .. /^$/); # skip header lines s/^/> / if (/^$/ .. eof()); # quote body As a list operator: for (101 .. 200) { print; } # prints 101102...199200 @foo = @foo[0 .. $#foo]; # an expensive no-op @foo = @foo[ -5 .. -1]; # slice last 5 items The range operator (in a list context) makes use of the magical autoincrement algorithm if the operands are strings.[32] So you can say:
@alphabet = ('A' .. 'Z'); to get all the letters of the alphabet, or: $hexdigit = (0 .. 9, 'a' .. 'f')[$num & 15]; to get a hexadecimal digit, or: @z2 = ('01' .. '31'); print $z2[$mday]; to get dates with leading zeros. You can also say: @combos = ('aa' .. 'zz'); to get all combinations of two lowercase letters. However, be careful of something like: @bigcombos = ('aaaaaa' .. 'zzzzzz'); since that will require lots of memory. More precisely, it'll need space to store 308,915,776 scalars. Let's hope you allocated a large swap partition. Perhaps you should consider an iterative approach instead. 2.5.16 Conditional OperatorTrinary
much like an if-then-else, except that it can safely be embedded within other
operations and functions. If the printf "I have %d dog%s.\n", $n, ($n == 1) ? "" : "s"; Scalar or list context propagates downward into the second or third argument, whichever is selected. (The first argument is always in scalar context, since it's a conditional.) $a = $ok ? $b : $c; # get a scalar @a = $ok ? @b : @c; # get an array $a = $ok ? @b : @c; # get a count of elements in one of the arrays You can assign to the conditional operator[33] if both the second and third arguments are legal lvalues (meaning that you can assign to them), provided that both are scalars or both are lists (or Perl won't know which context to supply to the right side of the assignment):
($a_or_b ? $a : $b) = $c; # sets either $a or $b to equal $c 2.5.17 Assignment OperatorsPerl recognizes the C assignment operators, as well as providing some of its own. There are quite a few of them: = **= += *= &= <<= &&= -= /= |= >>= ||= .= %= ^= x= Each operator requires an lvalue (a variable or array element) on the left
side, and some expression on the right side. For the simple assignment
operator, $var as if it were written: $var = $var except that $var[$a++] += $value; # $a is incremented once $var[$a++] = $var[$a++] + $value; # $a is incremented twice Unlike in C, the assignment operator produces a valid lvalue. Modifying an assignment is equivalent to doing the assignment and then modifying the variable that was assigned to. This is useful for modifying a copy of something, like this: ($tmp = $global) += $constant; which is the equivalent of: $tmp = $global + $constant; Likewise: ($a += 2) *= 3; is equivalent to: $a += 2; $a *= 3; That's not actually very useful, but you often see this idiom: ($new = $old) =~ s/foo/bar/g; In all cases, the value of the assignment is the new value of the variable. Since assignment operators associate right-to-left, this can be used to assign many variables the same value, as in: $a = $b = $c = 0; which assigns List assignment may be done only with the plain assignment operator, while (($key, $value) = each %gloss) { ... } next unless ($dev, $ino, $mode) = stat $file; 2.5.18 Comma OperatorsBinary " $a = (1, 3); assigns For example, if you change the above to: @a = (1, 3); you are constructing a two-element list, while: atan2(1, 3); is calling the function atan2 with two arguments. The 2.5.19 List Operators (Rightward)The right side of a list operator governs all the list operator's arguments, which are comma separated, so the precedence of list operators is looser than comma if you're looking to the right. 2.5.20 Logical and, or, not, and xorAs more readable alternatives to
The precedence of these operators is much lower, however, so you can safely use them after a list operator without the need for parentheses: unlink "alpha", "beta", "gamma" or gripe(), next LINE; With the C-style operators that would have to be written like this: unlink("alpha", "beta", "gamma") || (gripe(), next LINE); There is also a logical xor operator that has no exact counterpart in
C or Perl, since the other XOR operator (
2.5.21 C Operators Missing from PerlHere is what C has that Perl doesn't:
|