=head1 NAME perlbasics - Perl Basics for Sysadmins =head1 DESCRIPTION This is a tutorial introduction to perl for sysadmins. =head1 Introduction Perl is a free programming language created by Larry Wall and maintained by a huge group of talented and dedicated volunteers. Perl has been called I and will likely forever be so. In the words of it's creator, perl makes I. It is a rich language that helps you program all manners of sysadmin tasks quickly, scale/grow them and maintain them well though their lifetime. =head2 Objective The goal of this document is to introduce you to perl. By going through this document, you will be able to create simple programs in perl for your everyday needs as a system administrator. In addition, the examples in this document material can be used as starting point for more complex scripts that you want to build but did not know how to begin. L<"Origins, History and Philosophy of Perl"> gives you a little history and perspective about perl. =head2 Organization of this document This material is organized in such a way that explanations of most of the concepts occur I they have been introduced. This way, you can try a few things and play around with a snippet and look forward to the gory details to follow. The exercises usually test what has been explained, but introduce a few things that have not been explicitly covered, so that you have an incentive to try them out and see what you get. =head2 Additional pointers for learning This document is not a substitute for programming, nor does it substitute the documentation that comes with perl! The more you code, the better you can program. What is not obvious is that the more you read, the lesser you B to program. It is B that you read the perl documentation available on your system. At the very least, you should try to read all the manual pages mentioned in this document. Reasonably competent system administrators can implement a lot of their common tasks by minor modifications to the program snippets available in the core documentation that comes with perl. L<"Resources"> section gives you details on where to look for complete and authoritative information. =head1 Origins, History and Philosophy of Perl Perl is currently the most convenient and popular language for writing Web/CGI programs, System administration scripts, Web/Database applications, and even complex Data mining and software engineering. There are many reasons for this massive adoption and the phenomenal success of perl. Some of them are given below. =head2 The birth Before perl was available on Unix, programmers wanting to build home brew solutions/systems used a mix of shell, awk sed etc. for quick turnaround, and used C only if speed and efficiency was needed. This saved a lot of time and development effort. However, programming quick tasks in C is not fun. Shell scripts, on the other hand, don't scale well in large environments or for large data sizes. Perl was born out of Larry Wall's effort to get over the limitations of such approaches. Not content with writing just another program, he wrote perl so that he can re-use it for atleast one other project. He then released it to the Usenet. The rest is history. =head2 Perl's chief strengths In the words of Larry Wall, I. Perl is designed to be like C: flexible and powerful enough to manipulate the machine's capabilities directly. Perl also helps the programmer prototype ideas and whip up a working solution much faster than in most other languages. Perl was originally used for manipulating text data (perl stands for I). But it excelled in data transformation and file manipulation and all manners of system tasks and quietly filled a huge niche of everyday programming for everyday tasks. =head2 A melting pot Perl is a I of Unix. It is a language built to emulate the best features of L, L, L, B, and many others. It adheres to the I of using simple tools and building complexity through stringing the tools together into a real solution. The only deviation is that all the powerful tools of Unix are now available as I in perl. This approach saves time, increases speed of programming (compared to C) and execution (compared to shell scripting), and reduces error by keeping the complexity in the language, instead of in the program. This makes it possible for perl programs to run virtually unchanged on all manners and flavors of O/S! =head2 Perl is like a Natural Language Perl resembles English more than you expect it to, because It borrows a lot of concepts from natural languages. For example, it uses (visually) distinct ways to refer to different types of variables: I, I, and I. By stark contrast, I computer languages do not let you figure out the type of a variable from it's name. Perl is designed to be learned once, but used many times. You typically learn a small subset of perl when you start, and learn more concepts as you go. Like a natural languages, perl allows you to program as you learn it. This makes it possible for you to be productive as you learn. This is very much like how a child and an adult are able to communicate reasonably well with their own levels of mastery of the spoken language. Perl allows local ambiguity in programs. This means that you can operate on some things I and know that they will be doing the right thing when the program runs. The programs are thus shorter, easier to read and make better sense. Contrast the following paragraphs: 1. Mary is 18 years old. Vijay is 19. Mary and Vijay meet everyday for music lessons. Mary and Vijay see Vinni and Vicki everyday after their practice. After meeting Vinni and Vicki everyday, Mary and Vijay go for a movie with Vinni and Vicki. 2. Mary is 18 years old, Vijay 19. They meet everyday for music practice. After practice, they meet Vinni and Vicki and they all go for a movie. The first paragraph is what programs in most other languages look like. The second paragraph is what an equivalent perl program might look like. Perl also borrows extensively from the best of other languages. Here is a simple table (courtesy of postings on the Usenet newsgroup B ) of the features in perl and where they originally appeared in common usage: ++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Ancestor(s) ++++++++++++++++++++++++++++++++++++++++++++++++++++ range operator(..) awk, sed math operators (+,*,/) FORTRAN match operator (=~) awk scalars as number/string sh, awk, lisp varying length strings BASIC, awk substr awk lists lisp, APL, shell slices Ada, FORTRAN statement modifiers BASIC-PLUS glob('*') csh blocks Algol #comments shell system functions Unix, libc $ for variables shell quotes (', ", and `) shell m//, s// sed sort qsort from libc do, if, while, for C foreach shell OO setup python UNIVERSAL class smalltalk? unless, until BASIC-PLUS require LISP \u,|u,\l,\L vi $0 is changeable sendmail \w,\s emacs formats FORTRAN, COBOL, BASIC \e, $% troff grep, map LISP BEGIN, END awk chr, ord Pascal -e, -f, -d /bin/test from Unix! pack 'u' uuencode and, or, not REXX autoloading in modules lisp /i flag grep $package'variable (obsolete) Ada open syntax shell [] and {} dynamic structs python sub arguments shell, lisp tied arrays BASIC-PLUS system calls, networking Unix, C =head2 Tim Toady Most programming languages have a minimalist set of constructs (succumbing to I of design). There is usually I to do a particular task in such languages. Perl differs from such languages. It has been designed with redundancy in mind: multiple constructs abound that do almost similar things. If programming in other languages can be equated to a walk through a maze with orthogonal turns, programming in perl feels more like a walk through the grass in a park. This has led to the perl motto B, abbreviated to TMTOWTDI or I. This philosophy makes experimentation possible and keeps programming from becoming a boring chore. It also makes perl programming accessible to all levels of programmers. The better you get, the more concise and clear your programs get, and the more you start to use common I and the more you recognize how much less you need to write. =head2 Extensible The most current version of perl is version 5. Version 5 has been built with extensibility in mind. This has resulted in the largest collection of perl extensions (called Modules), and a group of volunteers who actively maintain the archives called CPAN (http://www.cpan.org/). =head2 History For a complete history, see the perl history web site listed in L("References") or try C. Here are some high points: The first version of perl was released in 1987. After successive refinements version 4 of perl was released in 1991, which also coincided with the first release of I book, I. Perl version 4 quickly became very popular. As many people started using perl for more than a few simple tasks, the limitations of the language made it difficult for people to add new features. To prevent perl from forking into many versions, a complete rewrite of perl was done and released as version 5. Perl version 5 was more extensible than version 4. It contained large-scale-programming features, added completely new features like lexical variables and closures, re-hauled regular expression engine, references, and made it possible to pretty much extend perl infinitely. Version 5 supports more operating systems; the standard distribution comes with a clean abstraction for database support (DBI), a Tk port to perl (Perl/Tk) and boasts a Win32 port for PCs running Microsoft operating systems (this port has since been integrated into the core perl distribution in source form). For the most current updates and feature list for perl, you should see the distribution, which is always available at http://www.perl.com/CPAN/src. =head1 Simple Program Example We will start our session with a simple example. Before going into the example, we need a digression on how perl runs your program, and also on how you run a perl program. Perl is an I language. This means that your program can be run without being converted into a I form. Your source program I the executable. The fact that it is interpreted means that you can greatly reduce development and build time. Is is also I. That is, perl will read your source program and compile it into an internal format before running it. The fact that it is also compiled means that it is much faster than I interpreted languages like Basic or TCP. You run your perl programs just like you run Unix shell scripts. You can call perl with I, or specify the location of your perl binary as the first line of the script and run the script directly. We will use B as the location of the perl binary in all our examples, but please replace that with the appropriate location for your site before running programs from this document. Here is the listing of a simple example program: 1 #!/usr/bin/perl -w 2 use strict; 3 my $who; 4 my $day = (localtime)[6]; 5 6 print "What's your name? "; 7 chomp( $who = ); 8 9 if ($day == 5 ) { 10 print "Have a nice weekend, $who!\n"; 11 } 12 else { 13 print "Have a nice day, $who!\n"; 14 } In line 1, we specify that this program is a perl script (on Unix like systems only). This makes your kernel arrange for perl to run this program when it's invoked by it's name. In line 2, we tell perl to use I variable and prototype checking. This is not mandatory. However, we will always use it to catch errors and silly mistakes early. In lines 3 and 4 we declare two I variables. Line 4 also sets the variable I<$day> to the day of the week (which is available as the seventh element of the return value of the I function in perl, which mimics the standard C library function call of the same name). Our code uses the number B<6> to pull the seventh element because perl arrays are usually indexed starting at 0. (It is possible to override this setting but we usually don't). Line 6 prints a prompt string to standard output (which is usually your terminal for interactive scripts like this example). Line 7 does many things. It uses the perl I operator, B<<\>> to read one line from STDIN (which is usually the terminal in interactive programs like this). This value is now stored in the variable I<$who>. The function I removes the trailing newline in the variable I<$who>. At the end of line 7, we have the user's input (minus the newline character) stored in the variable I<$who>. Lines 9 through 14 illustrate I in perl. Conditional branching in perl is similar to the C or shell `B' statement. In line 9, we check if the value of I<$day> is 5. The standard C library returns a number between 0 and 6 for the day of the week, 0 being Sunday. Thus, we check if I<"today is Friday">, and print the appropriate wish in lines 10 and 13. At line 14, the program ends, and perl does it's normal cleanup and exits back to the calling program (our shell). To run the above program we will save it into a file and invoke it. To follow a convention, we name it as I (plx is the current custom to name a perl `executable'). You should make the program executable by doing a B. Now, assuming you have the program under your current working directory, type: ./wish.plx This program illustrates quite a lot of perl, so let's go over the major features that we have illustrated, line by line, along with pointers to appropriate sections of the perl manual pages available with your perl distribution: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Line Description ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 O/S will invoke perl to run your program (perlrun) 2 Make perl check for common mistakes (perlrun) 3,4 Variable declarations (perlfunc, perldata) 6 print function (perlfunc, perldata) 7 chomp, <> operator (perlfunc, perlop, perlvar) 9..13 conditional branching (perlsyn) == operator (perlop) string interpolation (perldata, perlop) braces {} (perlsyn, under `Compound Statements') =head1 Basic Data types in Perl Almost all programs and scripts manipulate data. This is fairly obvious, but the kind of basic data types available in your programming language largely determines the kind of programs you can write easily and write well. Most programming languages give you a basic set of data types and constructs to build complex data types with them. They differ in the amount of management overhead in building complex data structures and/or algorithms from basic data types and operations. Perl provides you with three basic, but powerful data types. Unlike most languages, perl allows you to grow/shrink them dynamically without you ever having to worry about memory allocation/de-allocation. Perl does it all for you. The three fundamental data types in perl are called I, I and I. =head2 Scalars A scalar is the fundamental data type in perl. A scalar can hold a single value. This value may be a string, number, a file-handle or a reference to another perl data type. Strings and numbers are a sequence of characters. Filehandles are special values used as place-holders to refer to open files in your program. In short, a scalar value can be equated to the English word 'the'. Scalars are prefixed with a dollar sign(B<$>). I spite of the apparently different types of values you can store in a scalar variable, perl stores them in one format and converts between them as usage dictates. Here are some examples: $a = 'this'; #stores the string 'this' in $a $nirvana = 42; #stores the number 42 in $nirvana $ref = \$a; #stores a reference to the variable $a in $ref $hostname = 'foobar-blech.com'; You can build a scalar from other scalars through numeric and string operations. The most common operation used for building scalars is I. A double-quoted string containing scalar variables inside it will be automatically interpolated with the values of the scalars. Here is an example: $a = 20; $b = 22; $c = $a + $b; $answer = "The sum of $a and $b " . "is $c\n"; print $answer; This prints: I The `+' operator is the familiar numeric addition. The `.' operator is the string I operator that concatenates it's left and right operands and returns the result. As you may have noticed, a semicolon terminates a perl statement or declaration. You can also group multiple statements into a I by grouping them within curly braces. =head2 Exercises =over 4 =item 1 How do you define a scalar variable named I and initialize it with the result of 5% of 92? Can you do it in one statement? =item 2 What is the value of I<$bar> in C<$bar = 'abc' x 4;>? Try it! =item 3 How do you generate the full path of a file given it's name and the directory in which it is found? Given the directory in C<$dir> and the filename in C<$file>, what is the perl statement that will store the full-name in C<$full_path>? =back =head2 Lists and Arrays A literal list is a collection of scalar values. Lists are stored in perl I. Thus, an array is a list each of whose element really contains a B value. This is an important point that will help you manipulate list elements without confusion. As with scalars, lists can be built dynamically, and their size can be increased or decreased by adding, deleting or splicing elements at will. List names act like the English word `these'. You prefix an array with the B<@> character. However, to get the I element of an array, you provide the index of the element within square braces and prefix the name of the array with a B<$>. Here are some examples: # #declare variables (and save ourselves from headaches) my($borderline, @living, @server_ports); #scalar value is assigned here $borderline = 'prions'; #array assignment @living = ('plants', "animals", 'viruses'); #another way, now avoiding the annoying quotes @server_ports = qw(http smtp pop3 telnet ftp); #explicit assignment to AN element of an array $living[3] = $borderline; Note that each element of the list is a scalar. You can add/modify/delete them using different perl functions and operators. Here are a few examples: #Initializing/Adding to arrays my(@a) = ('this', 'that', 'and'); #define an array named `a' push @a, 'others'; print "@a\n"; #prints `this that and others' #Modifying existing elements $a[0] = 'you'; #0 is the first element. It is a scalar. $a[1] = 'me'; print "@a\n"; #prints `you me and others' my $size = @a; #$size gets 4, the number of elements in @a! $size = scalar(@a); #same as above pop @a; #deletes last element of array (and returns it's value) @a =(); #deletes everything in @a =head2 Exercises in Lists/Arrays =over 4 =item 1 Initialize an array named C to contain the user-names root, admin and http. =item 2 Add the user-name C to the above array. What happens if you use C instead of C? Try printing out the array in both cases and find out! =item 3 The B function returns the last element of an array and deletes it at the same time. There is another perl function that returns the B element of an array B deletes it after returning it! It has the same name as a Unix shell operation that does the same thing. Try to use L to find out more details. =item 4 How do you delete all elements of an array? What does undef(@array) do? =back =head2 Hashes The final perl data structure we will see is a hash. A hash is very much like a list, but it is indexed by strings (a list is indexed by number). A hash is like a database indexed by a single key field. Hashes are initialized by specifying the key and value in pairs. For example: %colors = ( 'red' => '#FF0000', 'green' => '#00FF00'); %passwd = ( 'root' => 'ez2Krack', 'mysql' => 'se1ect!'); Hash keys are strings and hash values are scalars, so you can refer to them in any place where you would need a scalar value. The individual key is enclosed within curly braces to specify that we are referring to a hash. Here is an example of adding another element to one of the above hashes by using a value stored in it: $colors{'blue'} = $colors{'red'}; Here is how it works. C<%colors> is the hash. It's name is I. The key for which we want to create a value is I. So the actual value is at key 'blue', which is a scalar: Key => 'blue' => 'blue' hash => curly braces => {'blue'} Scalar value => $ => $colors{'blue'} Here's another: print("Root password is too $passwd{root}\n"); =head1 Some simple Operations on variable types You can;t accomplish much with data alone. You must be able to manipulate it. Perl, like every language, provides many basic operations to manipulate variables. However, unlink most languages, most of these operations are very I and there are many groups of operations that do similar things. =head2 Scalars: length, substr, tr, s, chomp, lc, uc, int, sprintf Try each of the below statements and see if the result matches with the comments (You can ignore anything followed by a '#' because those are comments): $dozens = int( 97/12 ); # gets 8 $_ = 'A single sentence.'; $l = length($_); #$l is now 17 $is = substr($_, 9, 4); #$is is now 'is' $_ =~ tr/st/tp/; #$_ is now 'A tingle tenpence.'; $_ =~ s/t/s/; #$_ is now 'A single tenpence.'; print uc($_); #prints "A SINGLE TENPENCE."; $pi = sprintf("%.4f", atan2(1, 1)*4); #$pi gets '3.1416'; =head2 Lists: push, pop, shift, unshift, sort @a = (1, 2, 3); $last = pop @a; #$last gets 3 unshift @a, 0; #@a is now (0,1,2) @sorted = sort('jack', 'jill', 'fred', 'barney'); print "@sorted"; #prints `barney fred jack jill' =head2 Hashes: keys, values, each %h = ('emacs' => 'RMS', 'perl' => 'Larry', 'python' => 'Guido'); @software = keys %h; @authors = values %h; while ( ($k, $v) = each %h) { print "$k was the brainchild of $v\n"; } For an explanation of B loop, see L<"A little looping">. Verify that the above code gives the below output (not necessarily in the same order): emacs was the brainchild of RMS perl was the brainchild of Larry python was the brainchild of Guido =head2 Exercises for hash variables =over 4 =item 1 Define a hash called %IP. Use it to store a few IP addresses keyed by their hostnames. Save all the keys into an array called @hosts. Print the array @hosts as well as each of the key/value pairs in %IP. =item 2 Since hashes are indexed by strings, there is no 'order' to getting back the keys or values. You would use the I function to do this. Try to lookup this function in the perl manual pages (I). If possible, modify your program for the above exercise so that it prints the hosts and IP-s sorted by hostname. =back For more on this, see L. =head1 Statements, Variables, Context and meaning Everything in perl is an I. An expression is a basic unit of program in perl that returns a result. For example, the C statement in perl is actually an expression that returns a value. $result = print("Foo\n"); A perl statement is merely an expression evaluated for side effects. For example, we almost always never need to use the return value of an expression that contains a print statement. Thus, we write the print statement as below, and ignore the result: print "Result of previous stmt = $result\n"; Expressions can not only B results, but can also be B under appropriate conditions. When the return value of an expression is merely used to assign it to something else, it is said to be used as an B. In contrast, when you assign B an expression, it is said to be used in an B context. Quite a few of perl functions/operations can act as I. This is quite contrary to most other languages, so you may need to try a few examples to get familiar with this concept: 1 $_ = "ABC\n"; 2 print substr($_,1,1); #prints 'B' 3 substr($_, 1, 1) = 'C'; 4 print; #prints 'ACC' In line 1, we assign the value "ABC\n" to the perl builtin variable $_. The variable $_ is the default value used in quiet a lot of perl constructs where an argument is not explicitly provided. In line 2, we use a perl function I. This function takes 3 arguments: substr( EXPR, OFFSET, LEN) The first argument is an expression. The second argument is an offset and the third argument is the length. B returns a sub string of length I in I starting at offset I. String offsets start at 0, like most other offsets in perl. Thus, the result of line 2 is to print one character starting at position 1 in the string "ABC\n", which happens to be "B". In line 3, we see that substr actually returns the I in C<$_> which begins at offset 1 and has a length 1. This is namely the part of "ABC\n" that starts at "B" and ends right there (length is 1). When we assign 'C' to this expression, perl does something very natural: it B the substring "B" in "ABC\n" with "C". Thus, the original string is converted to "ACC\n"! This may need getting used to, because there are very few equivalents of such flexibility that you will find in other languages. Expressions can also return different things based on the B in which they are called! The two major types of context are described below. We will not discuss the I context which is a special case where you throw away the return value(s) because the side effect of that operations may be more important and relevant that it's return value. (L is an example). =head2 Scalar context A scalar context expects/returns a single scalar value. If you use an expression in a scalar context, the expression I it's return value(s) are coerced into a scalar. For example: $count = @lines; Here, @lines is an expression that returns a list of all elements contained in the array @lines. This expression is forced into a scalar context by the assignment statement. In a scalar context, this gives the number of elements of the array @lines. Thus, $count will really contain the I in the array @lines. =head2 List context A list context expects/returns a list of scalars. If you use an expression in a list context, the expression I it's return value(s) is/are coerced into a list. For example: @lines = ; Here, @lines provides a list context to the expression . This in turn makes the expression slurp the entire STDIN (until an eof or CTRL-Z) and return it as a list of lines. Thus, if you were to type 10 lines in the terminal followed by a CTRL-D after this statement, @lines will contain 10 elements, each of which will contain the respective line you entered. In this example: @one = 1; B<@one> provides a list context to the single value 1. The value 1 is coerced into a I whose first and only value is 1. Thus, the result here is that @one will now contain I element with value 1. This works for lists in general, but there is a special case of a B that you should be aware of: A literal list appears like a "C comma operator" in a scalar context. Here is an example to illustrate this important distinction: @a = (12, 0, 32, -23); $b = @a; print "b = $b\n"; $c = (12, 0, 32, -23); print "c = $c\n"; this prints: b = 4 c = -23 For more on context, see L. =head2 Exercises =over 4 =item 1 What are the two useful contexts in perl? =item 2 What happens if you assign a single scalar to an array? =item 3 Try out the following lines of perl code. Can you reason out what is happening? Try consulting I, or I man-page to see if it provides you more information: $\="\n"; #force a newline on every print print localtime(time); print scalar localtime(time); =back =head1 A little looping Most common tasks are repetitive. Like most languages, perl allows you to repeat a set of statements using I constructs. The two most common looping constructs are I and I. The I loop allows you to perform tasks while some condition is true, whereas a I loop is convenient to loop through a task a fixed number of times. Here are a few ways to do the same thing - print the numbers 1 through 10: =head2 Using `foreach' #perl style foreach my $number (1..10) { print "foreach $number\n"; } =head2 Using `for' #C style for (my $number = 1; $number <= 10; $number++ ) { print "for $number\n"; } =head2 Using `while' my $number = 1; while ( $number <= 10 ) { print "while $number\n"; $number++; } =head2 TMTOWTDI You can also loop through elements of an array, using the foreach loop, as follows: foreach (@some_array) { print $_, "\n"; } Or, you can repeatedly read from a file, until you hit the end of file marker : open(FILE, '/some/file') or die "/some/file: $!\n"; while ( ) { print $_; } The looping constructs are actualy far more versatile. For the full details, you should start at L. For more on this, see L. =head1 Perl Predefined Variables Predefined variables are builtin variables that automatically take on certain B<`sensible'> values at runtime. As we noted before, statements are expressions that return value(s). In the absence of an explicit assignment, some of the expressions take default arguments. In some expressions, perl may return the results unto certain default variables if you don't explicitly specify where they should be stored. In other cases, changing the settings of some internal variables will make the following perl program snippet behave differently. This may all seem rather confusing, but it helps us in writing uncluttered code. You will be able to understand them better with usage. You may someday actually depend on them! The following collection is part of the huge set of builtin variables in perl. We will follow these up with examples: =head2 Arguments, Environment etc. =over 4 =item @ARGV This is the complete list of arguments with which your program was invoked. You may use it as you would any other perl array. Here are some examples of @ARGV usage: print_help_and_exit() if ( @ARGV && $ARGV[0] eq '-h' ); if ( -f $ARGV[0] ) { die "File $ARGV[0] exists already! Won't overwrite!\n"; } Here is a program that prints all arguments passed to it. #!/usr/bin/perl -w use strict; my $arg; foreach (@ARGV) { $arg++; print "Argument $arg: $_\n"; } =item %ENV This is the hash of all environment variables that your perl program inherited from the calling program. The keys in this hash are all the environment variables that your perl program inherits from it's parent process. The values are, obviously, the actual values of those variables. Here is a simple perl emulator of the B command: while (($key, $value) = each %ENV) { print "$key=$value\n"; } =item @INC This is the include path for perl libraries. It's value is set at the time perl itself was compiled from source. Here is a simple example that prints out your perl library include path: foreach (@INC) { print "$_\n"; } Here is a one liner command to find out where any of the standard perl modules are located. We take "CPAN.pm" as an example: $file = 'CPAN.pm'; foreach (@INC) { print "Found $file under $_/$file\n" if ( -f "$_/$file"); } You can override this variable within your program. When you tell perl to use/require some libraries (eg. IO::File), perl will search all the directories in @INC for the Module/library. This is very useful for using perl libraries which you cannot install in your perl installation. You install them under a directory of your own and add to your @INC using the I pragmatic module. For example, if you have installed the latest cool whiz-bang version of Foo::Bar under your $HOME/lib directory, here is what you would do: use lib '/my/home/dir/lib'; use Foo::Bar; { #...whatever... } =back =head2 $_ = default input and pattern search space Whenever you use some perl construct which expects/returns a value and get away without an error/warning from the B<-w> switch, it means that perl managed to understand what you wanted, and stored it, or retrieved it from somewhere. $_ is the most common place for cases when the expected/returned value is a scalar. Example: while ( ) { split; } In the above example, which is a standard perl idiom, the operator returns a single line of input from the file pointed to by FH. In the absence of an assignment within the I conditional, it gets automatically placed in $_. The next statement I usually needs 3 arguments: the character/expression to split on, the value to split, and the number of values into which it should be split. In the absence of any of these values, the default value to split is $_. This makes the code above look much better than the one below, which doesn't assume many defaults: while ( defined($var = ) ) { @_ = split " ", $var; } =head2 @_ = default arguments for subroutines, default destination of 'split' As explained in the example above, the default destination of a split is @_. In the context of a subroutine call, @_ contains all the arguments to the subroutine. Note that perl subroutines can have a variable number of arguments on I invocation. @_ will automatically be sized accordingly. Since B<@_> is a global variable, the I value of @_ is restored as soon as the subroutine call ends! =head2 $. $/ $\ : File I/O counter, record separators When you use the EE operator to read data from a file, perl automatically stores the I in a variable named B<$.>. How does perl know where a line ends and the next one begins? Well, that is what the record separator variable, B<$/>, is for! As with most perl predefined variables, this takes on a default value. Here is a way to read in a whole file to a single scalar: $/ = ''; open(INPUT, 'tail -10 /var/adm/messages') || die "/var/adm/messages: $!\n"; $slurp = ; close INPUT; In the absence of an explicit assignment to $/, perl assumes that "\n" is the record separator between lines. If you clear this variable, as above, you can read whole files at a time. Similarly, every B statement will tack on the value of the builtin variable B< $\ > to every line/record you write. This variable is null by default, but if you want to, you can change this. See the B<-p> and <-l> variables in L for more usage information. =head2 $0, $$ : program name, PID When you invoke a perl program, there are two things that happen: firstly, the parent process that invokes the program (usually, your shell interpreter) forks itself. The calling program now takes on the role as the parent process and the return value of the fork call is the child's PID. The child process will be made to call the perl interpreter on your program. The name of your program is passed to itself as B<$0> at runtime. Similarly, the PID of your program is available as B<$$> at runtime. Type the following example into a test program, say, me.plx: #!/usr/bin/perl -w print "I am called as $0\n"; print "My PID is $$\n"; If you run it as, say, /your/home/me.plx, you will get something like this: I am called as /your/home/me.plx My PID is 2506 =head2 $! : O/S Error string or Errno Perl allows you to interact with your O/S, mostly through system calls for which it provides a perl function equivalent of the same name as the system call. If your system call fails for any reason, perl arranges for actual system error to be available as B<$!> variable. You may use this in two ways: If you use it as if it was a number, it will give you the actual B. If you use it as if it was a string, it gives you the system error string. If you ever get an O/S error code, you can find out exactly what it means using perl. Here's an example: /usr/bin/perl -e '$! = 2; print $!' Here is how this works: The first assignment to $! will set $! as if it was a number. The print statement expects a list of scalars as arguments, and thus $! will be retrieved in a string context, and hence will contain the system error string. The above statement should print B More typically, you use it like this: open(FOO, '/some/file') or die "/some/file: $!\n"; chdir('/for/bidden') or die "Can't cd /for/bidden: $!\n"; if ( !unlink('/read/only/dir/file')) { log_it_somewhere(); #your own logging routine, for example die "Can't delete /read/only/dir/file: $!\n"; } =head2 $?, $@ - Errors from child/pipe/eval When you call a program from within perl, usually using the back-ticks I<``> or I or I function, perl arranges for the status returned by the command to be available as B<$?>. $? also gets set if the last pipe returned a bad status. The actual value in $? is a combination of the exit status of the command, the signal it received (if at all) when it died, and whether the program dumped core while dying. However your program encountered any of these error conditions within an I statement in perl, the variable that is set is B<$@>. Example: `/etc/nowhere/hostname`; $error = $? >> 8; $signal = $? & 127; $core = $? & 128; print "Exit status of child: $error\n"; print "Caught signal $signal\n" if $signal; print "No core dumps\n" unless $core; prints: Exit status of child: 1 No core dumps =head2 $<, $>, $(, $) : real, effective uid/gid When you run any program, you typically run it as yourself, which is really a I and I. However, you may run programs that are setuid to some fixed user id, or setgid to some fixed group. In such instances, the program runs under the I uid/gid of the setuid/setgid program even though you have your own I uid/gid. Here is an example: perl -e 'print "UID = $<\n", "Effective UID = $>\n";' B<$(> and B<$)> variables have slightly different semantics because you can belong to multiple groups. Both of these variables return your primary group I a space separated list of all the groups to which you belong. See L for more information. =head2 Exercises =over =item 1 Write a program that tries to read a non-existent file, say, '/foobar/blech'. Your program should print out the system error code and die. =item 2 How do you automatically print a newline with every print statement? =item 3 Try to print the following builtin variables. Check with the I man-page to find out more: B<$]>, B<$^O> and B<$^X>. =back =head1 Perl Operators, Precedence To do anything useful with your data, you will need to operate on them. Perl provides the standard crop of operators and more. Here is a run down of some of them. For more details, read L. =head2 Mathematical Operators Most of the mathematical operators are available within the standard perl interpreter. The following table summarizes some standard operators: + Numeric addition - Subtraction * Multiplication / Division (floating point) % Modulus operator All of the above operands can also be used in conjunction with the assignment operator to shorten your code. Here are a few examples you can try: $total_size = $total_size + $size; $total_size += $size; #gives same result as above $usage_pct = 100.0*($disk_capacity - $disk_free)/$disk_capacity; $seconds_since_midnight = time() % 86400; #relative to GMT! $free_space_left = $current_free - $file_size; =head2 Numeric comparison To compare two numeric values, you use the numeric comparison operators in perl. This are very similar to those in C. Here are these operators, without much explanation. Try them out. +++++++++++++++++++++++++++++++++++++++++++++++++++ Operator Return Value +++++++++++++++++++++++++++++++++++++++++++++++++++ == true if left and right side are numerically equal != true unless left side is equal to right side < true if left side is less than right side > true if left side is greater than right side <=> returns -1 if left is less than right side (numerically) returns +1 if left is greater than right side (numerically) returns 0 if left is equal (useful for numeric sorting) Examples: if ( 2 == 2 ) { print "Yes, 2 == 2. What else did you expect?\n"; } =head2 String Comparison To compare two strings, perl provides a different set of operators. The behavior of these operators is identical to that of their numeric equivalents. The string comparisons are done in fashion very similar to the I C library function. eq, ne equality tests for strings (similar to == and !=) lt, gt strings (similar to < and > ) cmp similar to <=>, for strings Here are some examples: if ( 'A' lt 'B' ) { print "A is less than B\n"; } print "Which file do you want to change? "; chomp($file = ); if ( $file eq '/etc/passwd' ) { print "Do you really want to destroy this machine?\n"; } =head2 Logical Operators Logical operators return true or false. Perl has all standard logical operators. However, the meaning of true and false is different in perl, because perl considers strings and numbers to be the same data-type: Scalar. Here is a quick overview of truth as it applies to perl scalars: The empty string "" is false. Any string that evaluates to "0" is false. Any number that evaluates to 0 is false. Any I value is false. All else is true. Sometimes, this is surprising: 1 print "Yes\n" if ( "0.0" == ''); 2 print "What?\n" if ( "0.0" ); In line 1, we see that the string "0.0" is converted to 0 in the numeric context of the I<==> operator. The empty string on the right side is similarly converted into false. However, in line 2, the string "0.0" evaluates to I according to the rules. Thus, the print statement does get executed. Logical operators available in perl are I<&&>, I<||> and I. The logical I<&&> and I<||> operators are I operators, like in C. This means that the second operand is evaluated only when it's necessary. Here are some examples: $home = $ENV{HOME} || (getpwuid($<))[7] || die "No home directory!\n"; print "Your machine is wide open!\n" if ( $> && $< && -r "/etc/shadow"); For more on this, see L. =head2 Exercises =over =item 1 The B<-f> file-test operator checks if a file exists. The B<-s> file-test operator returns the size of any file. Write a program that asks a user for a filename and returns the size of the file, B! If the file is not found, you should return the system error message. =item 2 Write a program that takes exactly one argument and stores it in a variable called $infile. You can assume that the input will be a text file. Now, the program should open the file for reading, and count the number of lines. The program should print the filename and it's line count at the end. =item 3 What if your program above were given a binary file? Can you check whether the file is a text file programmatically and die if it is not a text file? See the B<-T> operator in the B man-page. =back =head2 Binding operators When you need to match a string with a pattern or make changes to it using a I match and replace, you use the I operator, B<=~>. To negate the logical sense of a match, you use the B operator. Here are some examples: $host = 'samba.org.au'; if ( $host =~ /\./ ) { print "$host seems to be fully qualified!\n"; if ($host !~ /\.(com|org|edu|mil|gov|net)$/ ) { $country = $host; $country =~ s#.*\.##; #remove everything except the TLD marker print "It's country of origin is: $country\n"; } } =head2 String operations There are two operations that you do on numbers that have analogues in a string. You may want to concatenate strings together, like adding numbers. Or you may want to concatenate the same string multiple times. There are string operators just for such needs. Here are the operators, by example: $config_file = 'resolv.conf'; $file = '/etc/' . $config_file; $recurse = 5; $GNU = 'GNU' . (' Not Unix' x $recurse); print "GNU expands recursively to: $GNU!\n"; Where do you use the 'x' operator? Well, here is a simple way to generate an attention grabbing notice: use Sys::Hostname; $stars = '*' x 79; $host = hostname(); $wall = "ATTN: Machine $host going down. Please logoff NOW!"; print "$stars\n$wall\n$stars\n\n"; =head2 Some new logical operators In addition to && and || for logical operations, perl provides B and Some new logical operators In addition to && and || for logical operations, perl provides B and B. These behave identically to the I<&&> and I<||> except that they have very low precedence. I determines the order of evaluation within a single statement. Here is an example where not knowing the precedence might bite you (in fact, the perl and/or operators were designed just so that people don't make this mistake). Perl allows you to call functions without using parentheses around the arguments. If you need to open a file, here is how you'd do it I parentheses around the arguments, without checking the return values: open(FOO, '/etc/passwd'); This can also be written conveniently as: open FOO, '/etc/passwd'; These two function calls work exactly the same way. Now, if you need to add some error checking of the return value of the I call, you would do something like this: open(FOO, 'bar') || die "bar: $!\n"; Unfortunately, the equivalent open FOO, 'bar' || die "bar: $!\n"; never works as intended. Why? Well, this function call is exactly the same as: open(FOO, 'bar' || die "bar: $!\n"); This is definitely not what we want. Remember that 'bar' always returns true. Thus, the die statement can never be executed! The unintended result is that if the open really bombs out, you would never catch it! This is a situation where the I comes to the rescue: open FOO, 'bar' or die "bar: $!\n"; This is clearer to the eye, and also works right. For more on perl operators, see L. =head1 Basic I/O, Filehandles and other file operations Perl provides lots of high level operations for file manipulation that would take quite a lot of work to do in other languages. Perl provides an abstraction called I to refer to open files in your program. This is very much like the file pointer in C. Perl provides a single function called I that allows you to access almost any data source with an amazingly simple and familiar syntax. =head2 Standard Filehandles Following the Unix convention, perl provides three default Filehandles that are direct analogues to C: I, I and I. In the absence of an explicit Filehandle, the magical spaceship operator (EE) automatically reads from STDIN. In the absence of an explicit Filehandle your I statements automatically print to STDOUT (You override this by using the L