Softpanorama
May the source be with you, but remember the KISS principle ;-)

Contents Bulletin Scripting in shell and Perl Network troubleshooting History Humor

Introduction to Perl 5.10 for Unix System Administrators

(Perl 5.10 without excessive complexity)

by Dr Nikolai Bezroukov

Contents : Foreword : Ch01 : Ch02 : Ch03 : Ch04 : Ch05 : Ch06 : Ch07 : Ch08 :


Prev | Up | Contents | Down | Next

2.4. Basic Control Structures


Introduction

Control structures are one of the strong points of Perl. It improves and extends C control structures in two major ways. First after if, while, etc there should always be a block (set of statements in curve brackets). That's just logical correction of classic "dangling else" problem that is present in C, C++ and other popular languages. PHP designers in their infinite wisdom even managed to reintroduce it back despite having Perl as a prototype ;-)

In Perl one should always use block of statements after all control structures

 Second it introduced several new variant of traditional control structures (unless) and new control statements for loops redo, etc. We will discuss this in more details in Ch.6. Right now we will provide a brief overview of control structures.

Sadly enough Perl redefined several of C loop control structure keywords, but we will discuss it later..

Perl view of true and false in expressions

Like C, Perl does not have a logical (Boolean) data type. An interesting innovation in C was that arithmetic expressions in conditional statements are evaluated and then converted to the integer value. In C if the result of expression evaluation is zero than it's false and if the result is not zero it's true.

Perl continues this C tradition with numbers and tries to extend it to strings. If expression evaluates to string than Perl treat it differently. In this case strings taken as logical expression are treated like integers equal to the length of the string -- empty string is considered false all others as true) . But the is an important exception -- string "0" is treated as false. I do not understand real reasons behind this decision, but you should be aware about it...

Not only empty string, but also string "0"(with length one) is treated as false in Perl

Like in C a variable (and by extension an assignment statement ) is acceptable as an expression in Perl. In this case the value of the variable is considered to be the value of expression. Like in C, you can write

if ($a) {...}
if ($a==1) { ... }
Does this pay in terms of programmer convenience versus additional bugs? Who knows. This C innovation proved to be a mixed blessing...

But generally Perl trades possible subtle errors for (sometimes incorrectly understood :-) convenience of programmer.

All in all Perl is probably the only language in which there are three different cases in which an expression evaluates to false.

1. Expression is false if it is considered numeric and evaluates to zero

2. Expression is false if it is considered a string and evaluates to an empty string (''), of string zero ("0")

3. Expression is false if it evaluates to an empty list

Collorary: Expression is false if it evaluates to the value undef .

Note that Perl does not convert string to numeric in logical expressions that involve text comparison. With a noted above exception of string "0" Perl just uses string length instead. That means that paradoxically if ("00") {... } evaluates to true just because it has length 2. All strings other than '0', empty (and undef) always numerically evaluates to true so, if ("a") {...} would be true too.

If we discount rather strange idea of adding "0" string to the false list it generally looks like more or less logical generalization of the idea used in the C language. C essentially substitutes Boolean data type with integer data type and treats 0 as false and any other integer value as true. Similarly strings of zero length can be treated as false and not zero as true. Here are examples of these four cases:

  1. Expression is false if it is considered numeric and evaluates to zero
    if (0) { } # false

    if ("0.0") { } # true because it is a string and it's length is more than one.

    if ("abba") { } # true

  2. Expression is false if it is considered a string and evaluates to an empty string (''), of string zero ("0")

    $a='';

    if ($a) {...} # false

  3. Expression is false if it evaluates to an empty list. We will discuss this later

    @X=();

    if (@X) {...} # we will discuss this later

  4. Expression is false if it evaluated to the special value undef. This is because in the numeric context undef will be converted to zero and in the string context it will be converted to an empty string. Both values correspond to false.

    if ($a) {...} # if we assume the $a was not used before, than this expression will be false

Comparison Operators

Perl adopted the design decision to use separate sets of comparison operators for numbers and strings instead of casting (for example by changing comment symbol to //(with discarding its usage for regular expressions too) and using prefix # for scalars that need to be converted to numeric (like in if ( $a==$b) instead of if ($a eq $b)). Also it would be nice to be able to control conversion to integer or to double float with declaration type statements like in ksh93. Currently one needs to use pragma use integer for this. That that's fantasy, and let's return to the reality that we need to face. String comparison operators in Perl are different from numeric comparison operators:

gt means greater than, lt is less than, eq is equal, and ne is not equal. There is also cmp -- a special three way comparison useful in sorting and searching.

These string comparison operators compare variables in the dictionary order. Any scalars (on one side of unary operators and on both sides of binary operators) are converted to strings before comparison.

So please remember that if you want to compare two numbers you should use == and to compare two strings you should use eq. This unfortunate dichotomy (or assembler style solution, if you wish) is a source on endless errors in Perl programs. Here are some examples of comparisons of numbers and strings.

$a == $b)        # Is numerical representation of $a(if any) 
	         # equal to numerical representation of $b (in double float) 
($a=$b)          # Beware frequent mistake: Don't use the = operator in If and check such situation as they are pretty common and pretty painful
($a != $b)       # Is $a converted to double float unequal to $b?
($a eq $b)       # Is string $a equal to string $b?
($a == "abba")   # Common error: using == instead of eq 
($a ne $b)       # Is string $a unequal to string $b? 

Logical Operators

All regular Boolean operation from C work as well. three principal Boolean operations are a !("NOT"), an &&("AND") and an ||("OR"). The following table shows the results from applying AND and OR operations to two compared states (operations are commutative):

!(NOT) &&(AND)
Minimum of two values
||(OR)
Maximum of two values

!0=1
!1=0

0&&0=0
0&&1=0
1&&0=0
1&&1=1

0||0=0
0||1=1
1||0=1
1||1=1

For a summary of Boolean algebra see Boolean Algebra. and Venn Diagrams for Boolean Logic, a color-illustrated explanation of Boolean Searching. See also explanation of Boolean Algebra in terms of set theory.

($a && $b)		# Is logical expression $a and expression $b true?
($a || $b)		# Is either expressions $a or $b true?
!($a)			# is expression $a false?

Both && and || are short-circuit. If the first operand evaluated to false in &&(AND) and to true in ||(OR) then the second operator is never evaluated.

Logical operators are mainly used in control flow statements such as if and while. Like in C they are short-circuit operators: if the first operator is true then in || the second operator is not evaluated and in && if the first expression is false, then the second expression is not evaluated.

Operator Description
exp1 && exp2 Performs a logical AND of the two variables or expressions
exp1 || exp2 Performs a logical OR of the two variables or expressions
!exp Performs a logical NOT of the variable or expression.

Each expression is producing result that is converted into a true or false value. Then either the value of the first expression or the value of the of both expression are used to determine the overall value of the op1 operator op2. Perl does not guarantee that the second expression will be evaluated.

"AND" Operator (&&)

The && operator can be understood as minimum operation on values of 0 and 1. Again I would like to stress that if the first expression was evaluated to zero the second expression is not evaluated at all (short-circuited).
Op1 Op2 Op1 && Op2
0 0 0
1 0 0
0 1 0
1 1 1

Example

if ($a < 10 && $a > 0 ) {
    print("Value of \$a is OK !");
}
If the first condition is false then we pass control to the statement located after the body of the if statement. If it is true that the second logical expression is evaluated and if it is true then the body of if statement is executed.

Or operator ( || )

The || operator can be understood as maximum for values 0 and 1 as two operands. This is also shirt-circuited operator. If the first logical expression is true then the second expression in not evaluated.

Op1 Op2 Op1 || Op2
0 0 0
1 0 1
0 1 1
1 1 1

If-then-else statement

Another very useful innovation in Perl is that both an if statement (and some loops, see below) has two symmetrical syntaxes: one for condition to become true to execute then part (regular if statement) and the other false (reversed if statement). The left variant in the table below is a regular if statement. The second is the same statement with the logical condition reversed -- then part will be executed if condition is false so it is equal if (!(.....)).

 This is a useful extension, but I would prefer the keyword ifnot.

if (expression) {
# Code block executed
# if condition is true.
} else {
# Code block executed
#if condition is false.
}
unless (expression) {
# Code block executed
# if condition is false.
} else {
# Code block executed
# if condition is true.
}

All statements in Perl are also expressions, so you can put arbitrary statement in the if. This is often used as a shorthand for input operations and later you will see a lot of idioms like while(<STDIN>) { ... } that use this possibility.

Perl improved syntax for if-then-else statements in comparison with C -- it does not accept a single statement in then or else clause and always requires a group of statements in curvy brackets as then or else clause. That is a really good decision as it prevents errors when the programmer in a hurry can add one statement thinking it will be in then (or else clause) and in reality it will be outside because there was only single statement in then or else group:

if ($cost > 100) {
   print "This item is too expensive\n";
} else {
   print "Price is OK. We need to think about it\n";
}
The curly braces around the statement block are not optional in Perl as they are in C. Even one-line statement blocks must be surrounded by curly braces.

That means that brackets around conditional expression are redundant, but currently for some unclear reason Perl does require them.

Brackets around conditional expressions are not optional. It's an error to omit them

The important think to remember is that Perl has two sets of conditionals -- one for numbers and one for strings. That creates a lot of problems for novices, but here -w flag can help to detect this unpleasant errors.

The main problem with Perl is that you may wish that operand will be interpreted an string but Perl will decide otherwise. For all numeric comparisons both operators are interpreted as numeric values. Please try to run the following two line script:

$answer="No"; 
if ($answer == "Yes") {
   print "The answer equals Yes";
}

Now you will see that you are in trouble. Both variable $answer and literal "Yes" will evaluate to numbers (zero in both cases) and comparison will always be for any non-number value of the variable $answer.

Empty string or uninitialized string (with value undef converted to an empty string) are considered to be false in Perl.

No else if style nesting are allowed. Cascading if statements can be created using the keyword elsif:

if ($name="SSH"){	 			# The first comparison
   print "This is a SSH protocol\n";
} elsif ($name="SSL"){				# The second comparison
   print "This is a SSL protocol\n";
} elsif ($name="IPSEC"){			# The third comparison
   print "This is IPSEC protocol\n";
} else {					# Default case- all conditions failed
   print "Unknown protocol";
}

If you are using several cascading elsif with all conditions being of the same type (for example checking for equality), you can make your code more clear by conversion of the values into array. For example:

#Wrong way to  perform the operation. 	Adapted from Medinets book 
	# Initialize  $month to 2.
# If the value of $month is 1, then print January. 
# If the value of $month is 2, then print February. 
# If the value of $month is 3, then print March. 
# For every other value of $month, print a message.

$month = 2;
if ($month == 1) {
    print("January\n");
} elsif ($month == 2) {
    print("February\n");
} elsif ($month == 3) {
    print("March\n");
} else {
    print("Not one of the first three months\n");
} 

Actually one should program this something like (note the usage of qw for simplification of creation of quoted list of words):

@year=qw(January, February, March);
if ($year[$month-1] != undef ) {
    print "$year[$month-1]";
} else {
   print "wrong index $month -- not in 1..3 range";
}

Typical if-then-else blunders

Perl inherited from C three language design blunders:

  1. usage of round brackets in if statements
  2. usage of assignment with low lexical distance between assignment statement ("=") and numeric comparison ("==").
  3. Usage of {} for blocks odf statements.

Blunders such as

if($i==1){

    # do something

}

Should be detected by Perl interpreter as they are meaningless but this is done only from, say. version of Perl 5.12 or so. Before that no warning was issued. More complex cases can't be detected by Perl interpreter, for example if there is variable on the right hand of the assignment that might be an intention of the programmer not an error.

The second blunder is connected with usage round brackets for expression in the if statement which in case of Perl are completly redundant. Due to this you can easily miss closing braket in situations lime

if ($b>length($text) { # note missing closing ")" 

}

And this situation is badly diagnosed  by Perl interpreter and couse of a lot of lost time. at least for some people like myself. One way to may it less frequent is to merge "redundand baclets with if and { correspondingly creating kind of new Perl lexems : "if(" and "){".

This can be done via editor search and replace and after such a transformation of your source it is much easier to see "who is swimming naked". For example: 

if( $b>length($text) }{ 

}

While usage of {} for block of statements is not a blunder per se, it became blinder because there is no way in perl to close multiple levels of nesting with a single bracket. The only meaningful way to detect such an error I know of is the usage of pretty printer. Fortunately there is a pretty printer for Perl that works well. And BTW you do not need to preserve pretty prited version of the program if you do not like the style of pretty printer. In this case you are using it as pure diagnostic tool. 

If-then-else expressions

In Perl like in shell you can use conditional expressions -- essentially if statements on the right side of the equal sign in the assignment statement. For example

($debug) && print __LINE__."\n"

In other words in Perl || and && operators are simultaneously flow control statements

In C tradition Perl has binary ``|'' and binary & as well as logical || and logical && operators. The latter in Unix shell tradition can be used for control flow control.

Logical "&&'' performs a short-circuit logical AND operation. That is, if the left operand is false, the right operand is not even evaluated. Scalar or list context propagates down to the right operand if it is evaluated.

Logical "||'' performs a short-circuit logical OR operation. That is, if the left operand is true, the right operand is not even evaluated. Scalar or list context propagates down to the right operand if it is evaluated.

Like in shell and unlike C the || and && operators return the last value evaluated.

The fact that both || and && operators return the last value evaluated means that you shouldn't use them for selecting between two aggregates in assignment:

@a = @b || @c;  # this is wrong
@a = scalar(@b) || @c; # do you really meant this ? Try it... 
@a = @b ? @b : @c; # this works fine, though

An often used Perl cliché for testing if opening of file succeeded is:

open(STDIN,$myfile) && die "Can't open file $myfile!\n";     
It also can be used as if-then statement:
( index($line,"Subject:")>-1 ) && $subject=$line;

This is the same as:

if ( index($line,"Subject:")>-1 ) {
   $subject=$line;
}

So it is not clear what we win by using this notation: it is not much shorter.

Another popular use is for controlling debugging statement, which are typically printing statement with a special variable $DEBUG:

$DEBUG=1;
... ... ...

$DEBUG && print "text='$text'\n"; 

Perl provides and and or operators as more readable alternatives to && and || when used for control flow. The short-circuit behavior is identical. The precedence of "and'' and "or'' is much lower, however, so that you can safely use them after a list operator without the need for parentheses. Still they are very rarely use.

 

Conditional Operator (?)

Ternary ``?:'' is the conditional operator, just as in C. It works much like an if-then-else. If the argument before the ? is true, the argument before the : is returned, otherwise the argument after the : is returned. For example:

printf "I have %d dog%s.\n", $n,
($n == 1) ? '' : "s";

Scalar or list context propagates downward into the 2nd or 3rd argument, whichever is selected.

$a = ($ok) ? $b : $c;  # get a scalar
@a = ($ok) ? @b : @c;  # get an array
$a = ($ok) ? @b : @c;  # oops, that's just a count!

This expression can ve on the left side of the assignment statement (pseudo-function) if both the 2nd and 3rd arguments are legal lvalues (meaning that you can assign to them):

(($a_or_b) ? $a : $b) = $c;

This is not necessarily guaranteed to contribute to the readability of your program. Because this operator produces an assignable result, using assignments without parentheses will get you in trouble. For example, this:

$a % 2 ? $a += 10 : $a += 2

Really means this:

(($a % 2) ? ($a += 10) : $a) += 2

Rather than this:

($a % 2) ? ($a += 10) : ($a += 2)

Loops in Perl

Perl is one of the few languages were loops are "done right.". Notation used is more flexible and more powerful that in C, C++ or Java despite the fact that the need for loops in scripting languages is less.

While, until and for loops in C have semantic similar to C. From shell languages a very useful loop -- called foreach loop was added. Several constructs for exiting loops were also added and in this respect Perl has better looping structuring facilities that any other language that I know.

Let me remind the key classification elements for loops which are applicable to any language:

Counting loop

Counting loop are based on not well understood Perl construct .. which in case of integers produced the loop with fixed increment equal to one. For example

foreach (1..12) {

   ... ... ...

}
This type of loops is very convenient if the number of iterations is fixed.

Implicit counter in this look is $_.  But it can be made explicit by changing the look into foreach type, for example:

$attributes=("rwe","r-w","r-w");
$groups=("owner", "group", "world");
foreach $i (0..2) {
  if (substr($attributes[$i],0,1) eq 'r') {
     print "$group[$i] readable\n";
  }
}

Later we will see that this loop can be understood as a special variant of foreach loop (see below). But, as we mentioned before, in the current Perl implementation, no temporary array is created when the range operator is used as the expression in foreach loops.

Also you can use keyword for instead of foreach, for example:

# equivalent to: for ($i=0; $i<12; $i++)
for $i (0..11) { 
   $s=$s+$days[$i]; 
}

Prefix loops

There are two forms of this loop -- one with body executed while condition is true and the second with the body of the loop executed while condition is false:

Terminating condition is checked for "true" Terminating condition is checked for "false"
while (expression) {
   ...; # statements
}
until (expression) {
   ...; # statements
}
	   

Prefix loops (called while loops) is most often used in Perl to read input from the file. This typical Perl construct should be used with caution. Here is an artificial example that will not work -- false condition for string can be empty string . The following will print out 'h e l l o' and stop:

@s = ('h','e','l','l','0',' ', 'w','o','r','l','d');
$i = 0;
while ($letter = $s[$i]) {
	print "$letter ";
 	$i++;
}

It does not print out the 'world' because of typo: zero was typed instead of the 'o' in 'hello'. At this point the value of $letter becomes "0" and the loop terminates. Please try to run this example via debugger.

Another example is also artificial but it shows inconvenience of pure prefix loop (code need to be duplicated):

print "Password? ";   		# Ask for the first input
$pass = <STDIN>;        	# Get input the first input
chop $pass;         	   	# Remove the newline at the end
while ($pass ne ":SeSaM:"){ 	# While input is wrong.  
				# Please  note the use of ne operator with string
    print "Sorry. Please reenter: "; # Ask again
    $pass = <STDIN>;       	# Get next input line
    chop $pass;            	# Chop off newline again
}
print "Welcome!\n";

The body of the loop -- the block in curly-braces is executed while the input does not equal the password. The code should be fairly clear, but please notice several things. First, we can read from the standard input (the keyboard) without opening the file first. Second, when the password is entered $pass is given that value including the newline character at the end. The chop function removes the last character of a string which in this case is the newline.

Logically this is a famous n+1/2 loop and as D. Knuth pointed out many years ago, it can not be adequately programmed using while or until constructs.

For arrays one can use while loop as a self-terminating loop (when array will be exhausted the next value will be undef):

while ($x[$i]) {
   print $x[$i]; $i++; 
}

But that is a danger that one of the array elements can be "0" or empty string (as we know Perl is incapable to check for undef and it is automatically converted to empty string or zero on comparison depending on the type of comparison operator), In such cases the loop will terminated prematurely. For example following loop will terminate after printing 123, before it will reach the last element:

@x = (1,2,3,0,5,6,7)
$i = 0; 
while ($x[$i]) {
  print $x[$i];  $i++;
}

An exit from while loop in Perl occurs, if you are dealing with an array or a hash, and you get zero elements in an array, i.e.: something evaluates to the empty list '()', the loop processing terminates. This also lead to subtle bugs. For example:

%weekend = {'St'->"Saturday','Sn'->'Sunday'};
while (($abbrev, $fullname) = each (%weekend)) {
   print "$abbrev $fullname";
}  
 

prints out all pairs (but not necessary in the order they were entered) and then stops. The loop stops when the last hash element has been put into this list. This form of terminating is very helpful when using function calls function can be programmed so that it will return '()' when there is no more output to produce.

Postfix loops

Here the condition is after the body and the body will execute at least once before the loop terminates. Like in if statement you can reverse condition. The following C-style syntax is used:

do {
...; # statements
} while (expression)
do {
...; # statements
} until (expression)

This example shows that the statement block is executed even though the condition $i < 0 is false when the loop starts.

The fact that zero evaluates to false permit creation of while loops that count down to zero. This is useful when you need a specific number of iterations and do not care about the fact that index decrease, not increase. For example:

$limit = 5;
$pageno=0;
do {
   printPage();
   $pageno++
while($pageno<=limit}

When this loop is done, all five pages will be printed. Actually this type of loop will behave wrong if you will specify negative number of pages, so regular for loop(see below) would be much better.

Here is example that we discussed in prefix loops rewritten using the postfix loop:

do { 
   "Please enter password: "; # Ask for input 
   $pass = <STDIN>; # Get input 
   chop $pass; # Chop off newline 
} while ($a ne ":SeSaM-1999:") # Redo while wrong input 

Here is another example of the postfix loop.

$i = 1;
do {
    print("inner loop iteration:  i = $i\n");
    $i++;
} while ($i < 0);
print("loop ended with: i = $i\n");

This program displays:

inner loop iteration:  i = 1
loop ended with: i = 2

Classic for loop

Perl has a for structure that mimics that of C. As in C it has the form

for (initialize; terminating condition; increment){
	statement;
	statement;
	...
}

First the statement initialize is executed. Then while test is true the block of actions is executed. After each time the block is executed inc takes place. Here is an example of the for loop to print how many day passed from the beginning of the year for the first of each month .

@month=( 'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');

@days = ( 31,   28,   31,   30,   31,   30,  31,    31,   30,   31,   30,   31);

$total=0;
for ($i=0; $i<12; $i++){
   print("$month[$i] \t $total\n"); # print total for the current month
   $total+=$days[$i];    # add days of the current month to total
}

It is clear that for loop without a counter is essentially equivalent to a while loop:

for (; i<12; ) {
   ... ... ...
}

The for loop without counter in Perl is an idiom for so called "forever loop", the loop that can be terminated only by a break statement inside the body and that does not contain terminating condition is the header to tail of the loop.

for(;;) {
   ... ... ...
}

Such loop is convenient when on the last iteration only part of the body of the loop needs to be executed. This is often he case in loops that deal with input.

The terminating condition expression is used to determine whether the loop should continue or be ended. When the condition expression evaluates to false, the loop will end. When writing the condition, be sure to use the numeric comparison.

The increment/decrement expression is used to modify the loop variables in some way each time the code block has been executed.

For arrays the usual way to loop through all the elements of an array is to use test $i<@month, for example:

@month=( 'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'); 

for($i=0; $i<@month; $i++) {	# Visit each item in turn				
	print "$month[$i]\n";	# Print the item
}

Foreach loop

This is a very popular form of loop that is typical for all scripting languages. Even extremely primitive DOS command.com batch language has a similar form of loop. For those with Unix background I would like to note that foreach is very similar to the "for..in" structure in Bourne Shell. In Java similar capabilities are provided by iterators.

Right now you probably will be better off skipping this section and returning to it after learning material of Chapter 3.

Foreach loop iterates through each of the elements of an array, by assigning each element to a temporary variable (this variable is actually a reference to the current element and changing it will change the element, see below) when iterating over an array or hash

The foreach statement provides a very convenient iteration mechanism without having to resort to a counter if one need to process all elements of an array. Therefore if task requires to scan an array checking each element, the foreach loop is a natural control structure to use. For example it can be used for finding the max/min (but built-in functions are better), various sums, selecting elements that satisfy some condition (if grep is not suitable for the task), etc.

The idea is very simple -- the body of the loop is executed once for every element of an array from the starting element to the end. On each iteration the value of the current element is assigned to a selected temporary variable:

@month=( 'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');

foreach $m (@month)	{	# Visit each item in turn				
	print "$m\n";		# Print the item
}

Here the loop control variable is $m. But it is a regular Perl variable. It is actually a reference to the element of array we process and is you change it in the loop you will change the element of the array.

As elements of an array can be generated using ranges, for ranges it is more understandable that a regular for loop (in the current Perl implementation, no temporary array is created when the range operator is used as the expression in foreach loops):

foreach $i (0..11) { # equivalent to 
	for ($i=0; $i<$days;$i++) { 
	$s=$s+$days[$i]; 
}

The foreach keyword is actually a synonym for the for keyword, so in this case I recommend using for instead of foreach:

for $i (0..11) { 
	$s=$s+$days[$i]; 
} 

If you do not need index, that the foreach loop is a perfect way to perform some calculation or select some elements of an array. In cases when one need to analyze the elements an array in sequence but actually do not need an index it is better to use foreach loop instead of for or while loops:

$total=0;  
foreach $item (@expenses) { 
   $total=$total+$item; # some calculation 
} 
print "Total expenses=$total"; 

The variable $item is assigned the value of each array element, in turn until the end of the array is reached. Actually it is better to use foreach loop instead of while loop in many cases like that.

Foreach loop can be used for hashes, but hash need to be converted to the array first. The idea is to use a special built-in functions (all of them are not limited to loops and can be used outside loops too):

The following code that prints all keys from the hash is pretty typical:

foreach $key (keys %hash) { 
	print $hash{$key}; 
}

The expression (keys %hash) will first generate an array containing all keys. Then this array will be used like in examples above -- in each iteration of the loop one element will be picked in sequence. We can rewrite this loop using values() function in the following way:

foreach $v (values %hash) { 
    print $v;
}

If we need to print both key and value that we should use each() function:

foreach ($v,$k) (each %hash) { 
   print "Key=$k, Value=$v\n";
}

From the point of view of memory consumption the function each() is the most economical as it does not create an array of all keys and all values as keys() and values() do.

Typical errors

See Typical if-then-else blunders Please note that in if and unless statement should have two closing brackets, if you use a function as a test. This situation is better visible if you use recommended style of "if(" and "){" separated with  a blank from the expression like in example below:

	if( open(SYSIN, "<$fname") ){
                |________________|
           |______________________|

In case, God forbid, you miss one round brackets, Perl diagnostic is really misleading. This is simultaneously a blunder inherited from C, own Perl blunder (Perl does not need those round brackets as it wisely does not allow single statement in if while and other similar statements (which was a great, pioneering decision of Larry Wall).

In nested loops or loops with conditional statement it is easy to mismatch brackets. That can be checked with pretty printer (perltidy). more time consuming method is to use editor function "find matching bracket". Most editors map it to shortcut Ctrl-]

As I already mentioned, pretty printer is a much better tool for finding such errors.

Prev | Up | Contents | Down | Next



Etc

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available in our efforts to advance understanding of environmental, political, human rights, economic, democracy, scientific, and social justice issues, etc. We believe this constitutes a 'fair use' of any such copyrighted material as provided for in section 107 of the US Copyright Law. In accordance with Title 17 U.S.C. Section 107, the material on this site is distributed without profit exclusivly for research and educational purposes.   If you wish to use copyrighted material from this site for purposes of your own that go beyond 'fair use', you must obtain permission from the copyright owner. 

ABUSE: IPs or network segments from which we detect a stream of probes might be blocked for no less then 90 days. Multiple types of probes increase this period.  

Society

Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers :   Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism  : The Iron Law of Oligarchy : Libertarian Philosophy

Quotes

War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda  : SE quotes : Language Design and Programming Quotes : Random IT-related quotesSomerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose BierceBernard Shaw : Mark Twain Quotes

Bulletin:

Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 :  Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method  : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law

History:

Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds  : Larry Wall  : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOSProgramming Languages History : PL/1 : Simula 67 : C : History of GCC developmentScripting Languages : Perl history   : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history

Classic books:

The Peter Principle : Parkinson Law : 1984 : The Mythical Man-MonthHow to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite

Most popular humor pages:

Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor

The Last but not Least


Copyright © 1996-2016 by Dr. Nikolai Bezroukov. www.softpanorama.org was created as a service to the UN Sustainable Development Networking Programme (SDNP) in the author free time. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License.

The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.

Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.

This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...

You can use PayPal to make a contribution, supporting development of this site and speed up access. In case softpanorama.org is down you can use the at softpanorama.info

Disclaimer:

The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the author present and former employers, SDNP or any other organization the author may be associated with. We do not warrant the correctness of the information provided or its fitness for any purpose.

Last modified: November 09, 2015