Perl can be a command line tool or it can be a simple scripting language like basic or shell and it can be an object oriented language with classes and packages like java. This is lesson book will introduce to all these different powers of perl, if you are not just reading this and I am talking to you, I will show you all of this in only an hour or two. I have faith that you will be able to take these notes home and write for yourself some useful programs, maybe to help calculate your finances, as I do. Every little program here extends into the next more complicated one. If at any point you get stumped, don't forget to shout out. It is very important to me that you understand that the combined baby steps will give the same abilities I have by the time we reach the last example. Command Line Perl: # perl -ne ' print "hello world\n"' hello world # This simple line is just like shell except that you have to add a newline character. The single tics keep inside statements safe from command line interpretation. # echo hello | perl -ne 's/hello/goodbye/ ; print' goodbye # This one-liner shows sed's pattern matching and substitution. # echo "ZxxxxZ XxxxxX" | perl -ne '/^Z.*Z$/ && print ' ZxxxxZ A slightly more complicated match, any line that starts and ends with "Z", give the boolean "yes" to the print operator to print the line. This can also be written as # echo "ZxxxxZ XxxxxX " | perl -ne ' $_ =~ /^Z.*Z$/ && print $_ ' #yields ZxxxxZ $_ is one of many special variables. I refer to this one as the "scalar in play." A scalar is a line of alphanumeric and character symbol text. The way to use a regular experssion (regexp) with a scalar is to use the =~ operator characters. I call this the "equals, sort of" operator. It returns the boolean "yes" if the scalar to the left is matched by the regexp to the right. The && operator says "if the last thing said yes then go on to the right." Here is a verbose version of the above one-liner: # echo "John Smith" | perl -ne ' $string = $_ ; if ( $string =~ /John/ ) { print "John is in his name $string\n" ; } ' #yields: John is in his name: John Smith # Here the shell command prints "John Smith " to the "standard input" of perl. The "e" in "-ne" says "run perl in the command line or "one-liner" mode, and the "n" says pump the standard input through from the left of the vertical bar, the "|" is called the "pipe" in linux parlance and it moves the output from one command, "echo" trough to the input of the command following it, "perl". The dash typical command line flag. A little more pattern matching: # echo "XXXX" xxxx " | perl -ne 's/x/y/gi && print $_ ' #yields yyyy yyyy The pattern matches for an x and substitutes it for a y. The "s" before the 0 means substitute and the "g" after the slashes and before the "&&" says "do it globally, meaning get them all (not just the 0 one) and the "i" after it means ignore upper or lower case. These matches are called regular expressions and perl is often embedded in other languages because it is very rich in these features. Besides the scalar there are two other "types" that we need to know about and those are arrays and hashes. An array is a list of scalars that are always kept in the same order. Each entry into the array has an index number where the first one is numbered "0". This is a sample array: # perl -e ' @test_array = ( 'aa', 'bb', 'cc', 'dd' ); print "this is the first, really zeroth value: " print $test_array[0],"\n" ' #this is the first, really zeroth value: aa When you are refering to the array itself you put an "@" sign infront. But when you want to print a value from the array, you put a "$" sign infront. This is because you are really refering to scalar inside the array, hence the "$" sign infront. Another way to use the one-liner with arrays follows: #echo "John Smith CXN, Inc. New York NY " | perl -ne ' @info = @_ ; print "name :", $info[0] ; print "comp :", $info[1] ; print "city :", $info[2] ; print "state:", $info[3] ; #yields: name :John Smith comp :CXN, Inc. ... and so on. Here perl automagically seperates each incoming line, and fills @_ which I call the "array in play". I copy the data to the @info and then I access each elements by index number through the print command. Missing from each print command is the "\n" you saw in the other examples. It is not needed to pring new lines because the newline is part of the string pumped in by the shell "echo" command. Hashes are a little more complicated. They can be thought of as a array of pairs of scalars where each pair consists of a "key" and a "value". A very common hash is used to define the "environmental" values of a linux login such as PATH and USER. # env | head PATH=/usr/bin:/bin:/etc:/usr/sbin USER=john ... ... Here the keys are PATH and USER and the values are to the right of the "=" sign. The following one-liner is several lines long but it shows how to use an array. The # symbol denotes a comment, anything after that is ignored until the next line. Every statement in ends with a ";" and lines not ending with it continue to the next line. # echo " 123 456 789 " | perl -ne ' while () { chomp ; # a special operator which removes # newlines from the "scalar in play" push ( @my_arr, $_ ) # Adds $_ to the end of the array } # "Blocks" begin and end with curly braces # not done yet !! foreach $num ( @my_arr ) { $sum = $sum + $num ; $cnt++ } print "Sum is:".$sum." Number of numbers: ".$cnt."\n" ; $string1 = "Average is: " $string2 = $sum/$cnt."\n" ; print "$string1 $string2" ; # Now we are done, note that you can even do math on a # print line. # dots connect things 0 into a single scalar # Now we end with the single tic that we started with ' #Sum is:1368 Number of numbers: 4 Average is: 342 Hashes are a little more complicated. They can be thought of as an array of pairs of scalars where each pair consists of a "key" and a "value". A very common hash is used to define the "environmental" values of a linux login session such as PATH and USER. # env | head PATH=/usr/bin:/bin:/etc:/usr/sbin USER=john ... ... Here the keys are PATH and USER and the values are to the right of the "=" sign. My last one liner will demonstrate how to use a hash, I hope you are all still with me here!! # env | perl -ne ' while (<>) { # You can remove STDIN here chomp ; ( $key, $val ) = split ( '=', $_ ) ; $my_hash{$key} = $val ; <- note this !!! } @key_list = keys %my_hash ; <- and this !!! foreach $key ( sort @key_list ) { print "Key is: $key Value is: " ; print "$myhash{$key},"\n" ; }' # It Yields: Key is: PATH Value is: /usr/bin:/etc:/usr/sbin Key is: USER Value is: john ... ... About the notes, $my_hash{$key} refers to a scalar in the hash, and @key_list = keys %my_hash uses the keys function to get a list of keys from the hash "%my_hash". The keys function returns an array of keys with which we fill "@key_list". This is about as far as I dare go with the "one-liner." It shows that perl can make the computational chores of everyday life both easy and enjoyable. Now I will move onto complete scripts. Copyright CXN, Inc., 2000, please email john@thinman.com for copy permission