Perl cornucopia

Need a Perl pick-me-up to see you through the long, cold Thanksgiving weekend? Then we've got the perfect bite-size chunks of Perl wisdom to help you out. Read these five handy tips for squeezing the most out of Perl.

It's been almost a month now since our weekly Perl newsletter went the way of the T-Rex and the Dodo bird. We figured right about now you'd be in need of a pre-Thanksgiving fix, so we pulled together the best of James Brown's unpublished Perl tips. We hope you enjoy these little morsels of Perl goodness. They go great either before or after you stuff yourself with turkey and pumpkin pie.

Finding all files that match a pattern
Perl’s glob operator makes it easy to find all files that match a given wildcard pattern.

The glob operator implements the same filename expansions that the standard Unix C shell (/bin/csh) would do. This allows you more complex options in matching filenames.

Some of the special search patterns that glob supports are:
  • *xxx* - Match entries with xxx anywhere in the name
  • {aa,bb,cc} - Match entries with either aa, bb, or cc
  • [a-f] - Match entries with any of the letters a, b, c, d, e, or f
  • a?b - Match entries with a, any single character, b

These can be combined in interesting ways. For example, the grouping operator {} can be used with the ? or * characters to generate multiple patterns such as:

That matches abc, afc, ame, are, and afg, for example. You cannot, however, combine grouping and character classes. For example, the following will not do what you expect:

This would only match afg and not any of the other patterns matched by the previous pattern.

The glob operator makes wildcard matching of files easy to implement. Give users the option of matching file names using this powerful matching functionality.

Using the repetition operator
Perl supports a special repetition operator that does not exist in most other mainstream programming languages. The repetition operator returns a string or a list repeated the specified number of times.

In scalar context the repetition operator returns a string of the left operand repeated the number of times specified by the right operand. For example, the following code prints a line of 80 characters of alternating dash and equals signs.
print '-=' x 40 . "\n";

In list contact, the repetition operator returns an array composed of the left operand (an array) repeated the number of times specified by the right operand. The following code prints 1 2 3 1 2 3 1 2 3.
@a = (1, 2, 3) x 3;
print join ' ', @a;

The repetition operator comes in handy when printing headers and footers in reports. For example, to print a header line followed by a dashed line below that is the same length as the header, which gives the appearance of being underlined, you could use the following:
print $header . "\n" . '-' x length($header) . "\n";

Perl’s repetition operator makes it easy to create strings or arrays of repeated data.

Using the modulus operator
Perl supports a modulus operator that returns the remainder after dividing by a given number. This comes in very useful in many circumstances. For example, when trying to convert tabs to spaces or when you want to repeat a header or other block at specific intervals in a list of output lines.

When the divisor is positive, the modulus operator is equivalent to the following code:
$modulus = $a - (int($a / $b) * $b);

The modulus operator can be used to calculate the number of spaces to insert when converting from tabs to spaces:
$tabstop = 4;
while (<STDIN>)
    1 while(s/^(.*?)(\t+)/$1 . ' ' x ($tabstop * length($2) - length($1) %


It can also be used to output a header after a certain number of lines (25 in this example):
$header = "\nPerl Tech Tips" . ' ' x 40 . "\n\n";

$count = 0;
while (<STDIN>)
    if ($count % 25 == 0)
        print $header;

    print "$count: $_";

Even though the count continues to rise, every 25 lines the header is output because the modulus operator returns 0 when the remainder is 0 after dividing by 25. Note that the header is output at the start of the run because $count is 0 and 0 / 25 leaving a remainder of 0.

The modulus operator comes in very handy when you need to calculate the remainder after an operation such as when converting tabs or repeating a block after a certain number of lines of output.

Perl's assignment operators
Perl supports a wide variety of assignment operators. Besides the ordinary assignment (=) operator, most of the binary operators are supported with the assignment operator to simplify your code.

The binary operator assignments consist of the binary operator followed by the equal sign. This is shorthand for having the left operand also appear on the right of the equals and being followed by the binary operator. An example using the addition (+) operator should make this clear:
$a += 2;
# equivalent to
$a = $a + 2;

The following list of binary operators with assignment is supported:
  • **= Raise to a power
  • *= Multiplication
  • /= Division
  • %= Modulus
  • += Addition
  • -= Subtraction
  • &= Bitwise and
  • &&= Logical and
  • |= Bitwise or
  • ||= Logical or
  • ^= Exclusive or (xor)
  • <<= Left shift
  • >>= Right shift
  • .= String concatenate
  • x= String or array replication

Unlike some other languages, in Perl all the assignment operators produce a valid lvalue (something that can be assigned to). Modifying an assignment is the same as making the assignment and then modifying the variable that it was assigned to. So, the following code increments the variable by 2 and then multiplies the result by 3.
($a += 2) *= 3;
# equivalent to
$a = $a + 2;
$a = $a * 3;

Perl’s assignment operators make it simple to write compact, easy-to-understand code. You do not need to repeat a variable name on the right-hand side of an assignment and you can make further assignments to the result of a previous assignment.

Differences between the different ands, ors, and nots
Perl provides several different versions of operators for and, or, and not. Choosing the correct one can be tricky unless you understand the differences between them.

The operators can be expressed three different ways in Perl:
Table A
Operation Bitwise Logical Lower precedence
AND & && >and
>OR >| || >or
NOT ~ ! Not
Perl operators

Bitwise operators do their work at the bit level. To understand what this means, you must understand the binary number system. Binary is base two so each succeeding column to the left represents a number twice as large. Here is a table of decimal numbers and their binary equivalents.
Table B
Decimal Binary
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
Decimal to binary equivalents

If we perform a bitwise and on 5 (0101) and 6 (0110), the result is 4 (0100) because that is the only bit that is set in both operands. A bitwise or of 5 (0101) and 6 (0110) results in 7 (0111) because all these bits exist in either number. A bitwise not of 7 (0111) results in 8 (1000) because it inverts each bit.

The logical versions of the operators work the way you would expect in an English sentence. For example, A && B means if A is true and B is true, then the result is true.

Precedence determines which operations are evaluated first. Back in elementary school we learned that the result of 2 + 3 * 5 should be 17 not 25 because the precedence of multiplication is higher than addition. There are times when you want the logical operators to bind more tightly (like multiplication) and times when you want them to bind less tightly (like addition). By selecting && or and, you can adjust the precedence of the operator to suit your situation.

Editor's Picks