This is a read-only archive. Find the latest Linux articles, documentation, and answers at the new Linux.com!

Linux.com

Feature: Perl

SysAdmin to SysAdmin: Approaching Perl

By Brian Jones on July 07, 2004 (8:00:00 AM)

Share    Print    Comments   

Writing an article about getting started with Perl is a bit like writing an article about getting started with neurosurgery. Sure, I could cover some basics -- but it would only leave you scratching your head the first time something comes up that you've never seen. I'd hate to see a neurosurgeon in that position! But no matter what you do, there are always times when you just don't know an answer. A much more horrible fate to suffer is to have no clue where to go to find the answer. So, this article covers one or two basics of Perl, just to show you that's it's not so scary, and a future article will tell you where to find solutions when you're on your own.

Many of the uninitiated who first see Perl immediately become intimidated by the arcane symbols, and strings that look as though a cat walked across the keyboard. If you're one of these people, fear no more. I myself was one of those people. Yet even I am now able to conquer common sysadmin problems large and small, using nothing more than a few lines of Perl. On occasion, I'm even impressed at the feats of greatness that Perl and I can pull off. In the end, sysadmins like Perl because Perl makes them look good.

Ah, but where to start? For me, the easiest way to get started is to "scratch an itch," so to speak. If you don't have anything urgent, porting old shell scripts to Perl provides a great exercise for learning how things are done in Perl. But of course, it helps if you have some clue of how the world looks through Perl-tinted glasses, so let's have a look at some basics.

What all the funny symbols mean

Perl uses lots of quirky symbols that look intimidating at first. However, once you understand what they mean, you'll realize that they are there to help you. These first three are used to indicate that a particular variable is of a particular type:

$scalar
@array
%hash

Any time you see a single "$" followed by a name, it's a scalar variable. A scalar variable can hold any type of value. Strings, numbers, floating point numerics, and even references to locations in memory can all be stored in scalar variables. These are probably the most frequently used variable types, since practically anything can be stored in them.

A single "@" indicates that the variable is an array. I tend to think of arrays as nothing more than a potentially random selection of scalar values. They are indexed numerically for you by Perl so that you can easily reference individual bits within the array later in your script. This one needs an example:

@days = ( 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');

Once I've declared my array and populated it, referencing individual values is as easy as asking for it by its index value. Index numbers start at "0," so if I'm looking to get back "Tuesday," I'd put the line print $days[2]; in my script.

A single "%" in front of a variable name signifies that it is a hash. A hash is just slightly more complicated than an array, but affords you the flexibility of assigning your own index, instead of using the default numeric ones Perl generates for you. So, suppose I need an array of user names, and an array of Unix shells, but I need the shells to be matched up with the right users. Instead of using two arrays and writing the code to match up values from them, I can just make the username the index for my hash, and make the shell of choice the value:

%usershell = ( jimi => '/bin/bash', eric => '/bin/tcsh', eddie => '/bin/csh', billy => '/bin/zsh' );

So now, if I want to know the shell assigned to "eric", I can just ask for it (almost) by name: print $usershell{'eric'};.

More symbol quirkiness, clarified

Why did I use a "%" to assign a hash, and a "$" when I wanted to print a value from it? This is initially confusing. Notice also that I did the same thing with our arrays, above. The reason is that, when I ask for a particular value of a hash or an array, I'm asking for a piece of scalar data, not an entire hash or array. Because I want a scalar value back, I use the "$," which as we discussed before indicates a scalar value.

The observant will then ask, "Well, you said that the symbols indicate the type of variable it is -- how do I know whether you're asking for a scalar value from a hash or an array?" The answer lies in the type of brackets used to ask for the value. As you can see in the above examples, the curly braces are used for hash values, and square brackets are for arrays.

But what if you have to reference something that you haven't explicitly defined in your script? Symbols to the rescue! Probably the most common symbol that I haven't covered yet is $_. This is sort of a placeholder or "default" variable used, for example, inside a subroutine to reference the arguments passed to it. Since you don't know what's being passed to a subroutine when you write it, you can just use this variable to represent the parameters. Sometimes, $_ can be implied -- for example, if you ever see a single line of Perl code which says, simply print;, the $_ is actually implied, though it's not incorrect to put it there if it makes things clearer for your brain.

Loops in Perl

I've coded in numerous languages, ranging from C/C++ to PHP and even a little Python. For loops, I still like Perl the best (though PHP 4 is almost identical in this respect). While Perl has a rather impressive array of looping structures, for brevity, I'll cover just two common loops: for and while.

The "for" loop is famous for allowing you to control iteration based either on an arbitrary number or value you invent, or on a value derived from somewhere else in your code. Here's a simple for loop that uses an arbitrary number I've created to determine the number of times the loop executes:

for ($count = 1; $count <= 10; $count++)
{
    print "$count\n";
}

This loop simply prints the numbers 1-10, with a line break after each number. Of course it's really quite rare that you can just make up a number like that. Generally, you want the number of loop executions to be based on some dynamic variable so you don't have hard-coded constants strewn about your code that may need to be changed at some point (causing you work, thereby defeating the purpose of scripting in the first place!). Here's something more realistic:

@users = ('eric', 'billy', 'eddie', 'yngwie');
for ($i=0; $i < $#users; $i++)
{
   &nbsp print "$users[$i]\n";
}

In the above example, I started with an array containing four values. I initialized $i to zero. Each time through the loop, I check and see if $i is less than the highest index value in the @users array. If it is, I keep going, incrementing $i by 1 each time through. Note that I snuck yet another symbol in here: $#, which returns the highest index value in an array. Since arrays are indexed starting at 0, the value should always be the number of values in the array, minus one.

The while loop

The while loop tests the input, and then executes statements based on the outcome of the test. This is often useful in situations where input is read from a file or from the keyboard, and you want to act upon each piece of input without knowing ahead of time what it is or how much of it there will be. Here's an example:

open (PASSWD, '</etc/passwd') or die "Can't open file: $!";
while (defined($acct = <PASSWD>)) {
  print "$acct";
}

This does essentially the same thing as cat /etc/passwd would do at the command line. The first line opens the /etc/passwd file and assigns a handle name to it called PASSWD. Then, I assign a variable to the value coming in from the handle (basically, a line of data from the /etc/passwd file), and if there is a value there, the loop executes. As soon as there ceases to be data in $acct, the loop stops executing.

In conclusion

Don't say I've teased you; I've not even written enough about Perl to accomplish that. I'd need another 5,000 words to feel like I've given you even half of a clue. However, I do hope that what I presented here will make the task of reading and writing some simple Perl code a little less daunting. If demand dictates, I'll continue in a future article with more advanced topics and regular expressions.

Share    Print    Comments   

Comments

on SysAdmin to SysAdmin: Approaching Perl

Note: Comments are owned by the poster. We are not responsible for their content.

Disapointing, No Book Resources

Posted by: baelbouga on July 07, 2004 07:42 PM
I am disapointed that there wasn't any reference at all to the PERL bible: 'Programming PERL'


Oreilly Books have produced, I think, the best collection of PERL books. (<A HREF="http://perl.oreilly.com/" title="oreilly.com">http://perl.oreilly.com/</a oreilly.com>)


The best place to start would be 'Learning Perl'. It is presented in a step by step manner taking you through the basics of PERL. It also teaches the most critical part of PERL: Think Like Larry!


Larry Wall, for the most part, created PERL and it helps to understand why he created it the way it is. Larry also co-wrote the 'Programming PERL' and it is the BEST single resource for information regarding PERL.


Please, if you're interested in PERL, check out Oreilly Books. They have helped me find that missing part more times than I care to admit.


--

Baelbouga

#

Yes More Perl

Posted by: Administrator on July 07, 2004 09:11 PM
I have been using Perl for years and more articles on Perl is always good. There are always noobies coming into the language and good writing on the technical aspects of Perl can do nothing but help.

Keep going!

#

ugh.

Posted by: njcajun on July 08, 2004 01:33 AM
Sorry for the typos, all. Thanks a bunch for the corrections! We'll get them fixed.

#

Re:The Perl way of iterating over an array

Posted by: njcajun on July 08, 2004 03:03 AM
True. However, I wasn't introducing "foreach" yet. The way I've done it in the article is a completely acceptable example of the "for" loop.

#

Re:Book Sources

Posted by: Administrator on July 08, 2004 12:36 AM
I know I am going to sound like an annoying crank, but please avoid shouting when you write Perl. People seem to think Perl is an acronym, so they write it as PERL, but I assure you, it is not. There are retronyms -- people made up acronyms after it was already named -- but these are just for fun, and shouldn't be used seriously. Common conventions are to refer to Perl the language with a capital P, and perl the executable program with a lowercase p.

#

Re:Oh Dear, lets look at arrays again

Posted by: Administrator on July 08, 2004 12:39 AM
This is exactly why I advocate using the range operator to iterate over an array's indexes. Not only is it easier to type and understand, it's less prone to off-by-one errors:
<TT>for $i (0<nobr> <wbr></nobr>.. $#array) {
    print "$array[$i]\n";
}</TT>

#

good one

Posted by: Administrator on July 07, 2004 07:05 PM
i am very new to perl and this article helped me
in clearing few doubts.You could have suggested
some books from beginer to advanced level in perl too.

#

Re:good one

Posted by: Administrator on July 08, 2004 08:36 PM
Another great sysadmin language you may want to look at is Python, it's much more consistent and readable than Perl. In the past it's had less mindshare but that seems to be changing.

#

Book Sources

Posted by: Administrator on July 07, 2004 07:35 PM
I am disapointed that there wasn't any reference at all to the PERL bible: 'Programming PERL'


Oreilly Books have produced, I think, the best collection of PERL books. (<A HREF="http://perl.oreilly.com/" title="oreilly.com">http://perl.oreilly.com/</a oreilly.com>)


The best place to start would be 'Learning Perl'. It is presented in a step by step manner taking you through the basics of PERL. It also teaches the most critical part of PERL: Think Like Larry!


Larry Wall, for the most part, created PERL and it helps to understand why he created it the way it is. Larry also co-wrote the 'Programming PERL' and it is the BEST single resource for information regarding PERL.


Please, if you're interested in PERL, check out Oreilly Books. They have helped me find that missing part more times than I care to admit.


--

Baelbouga

#

Oh Dear, lets look at arrays again

Posted by: Administrator on July 07, 2004 10:52 PM
Why not try below instead:
<TT>@users = ('eric', 'billy', 'eddie', 'yngwie');
for ($i=0; $i <= $#users; $i++)
{
     print "$users[$i]\n";
}</TT>
Semicolons are required. Managing to confuse Perl beginners about how to print out *all* the values from an array is not!

#

The Perl way of iterating over an array

Posted by: Administrator on July 08, 2004 02:18 AM
The "native" way to do this is:

@users = (eric, billy, eddie, yngwie);
foreach (@users)
{
print "$_\n";
}

or
@users = (eric, billy, eddie, yngwie);
foreach my $user (@users)
{
print "$user\n";
}

or

@users = ('eric', 'billy', 'eddie', 'yngwie');
print "$_\n" foreach @users;

#

Re:The Perl way of iterating over an array

Posted by: Administrator on July 08, 2004 02:21 AM
With some formatting this time:

The "native" way to do this is:
<TT>@users = (eric, billy, eddie, yngwie);
foreach (@users)
{
   print "$_\n";
}

or

@users = (eric, billy, eddie, yngwie);
foreach my $user (@users)
{
    print "$user\n";
}

or

@users = (eric, billy, eddie, yngwie);
print "$_\n" foreach @users;</TT>

#

Re:The Perl way of iterating over an array

Posted by: Administrator on July 08, 2004 03:34 PM
<TT>I would do it more like

@users = (eric, billy, eddie, yngwie);
$\ = "\n" ; print for @users;

which works by setting the output record separator to a newline, then prints all members of a list using the implicit $_ variable, and separates them with the output record separator.

Just to show that you can do a lot with perl's carefully chosen 'default' variables mentioned in the article.

If you replace the middle semicolon with a &&, it becomes '($\ = "\n") && print for @users;' quite close to unreadable for a perl newbie, but nevertheless a valid perl one-liner.

BTW: the loop in de code above is not needed, ie. it is allowed to remove the 'for'.
</TT>

#

Typo correction

Posted by: Administrator on July 08, 2004 01:11 AM
<TT>for ($count = 1; $count
{

print "$count\n";

}</TT>

#

About those sigils...

Posted by: Administrator on July 08, 2004 07:26 PM
It's misleading to think of the sigils (@,$,%,&,*) as saying what type of variable '@values' is, and means you don't get far before having to deal with things like $values[1], and the fact that $values, @values and %values are, at least superficially, completely unrelated.

Better to start out by thinking of it as saying what type the *value* is - if it's attached to an unqualified name then the value and the variable are the same type, but if not then what comes after the name tells you; $values[1] is from the array @values, $values{1} is from the hash %values, and so on.

That way, you can read things like

  %b = @values{1,3,5,'blue'}
without risking a headache<nobr> <wbr></nobr>:)

John.

#

Re:you're not a sysadmin if...

Posted by: Administrator on July 08, 2004 08:22 PM
Actually, the terse perl equivalent would be

  %usershell= qw(jimi<nobr> <wbr></nobr>/bin/bash eric<nobr> <wbr></nobr>/bin/tcsh eddie<nobr> <wbr></nobr>/bin/csh billy<nobr> <wbr></nobr>/bin/zsh);

  print $usershell{jimi}, "\n";
which isn't all that different.

The most important difference between perl & TCL is that TCL is a 'true' interpreted language, whereas perl is compile-then-run; as a result of this TCL has come with a 'real shell' since ages, whereas any Perl shell is, ultimately, either a somewhat lame hack or an incomplete implementation.

tclsh is a really neat debugging/doodling aid (especially 'wish', its TK-enabled cousin), but I still prefer Perl; if you're choosing between (or switching between) the two, think about the difference (compiled vs interpreted) - one isn't necessarily better or worse than the other, but the difference means that things that look like they 'ought to be' equivalent aren't always, because what your code does is being determined in a different context, at a different time.

John.

#

you're not a sysadmin if...

Posted by: Administrator on July 08, 2004 07:51 PM
Don't think that you're NOT or CAN'T be a sysadmin without learning Perl. I know enough perl to be able to read other scripts written in perl, and do some basic things in perl, but I prefer to do my sysadmin scripts in Expect or TCL/TK. (Expect is actually an extention to TCL.)

In TCL you don't have to worry about $ % @. All variables use a $. All these different notations for variables is just confusing. To show that TCL is simpler look at the hash example. To do the same thing in tcl type:


  array set usershell {jimi<nobr> <wbr></nobr>/bin/bash eric<nobr> <wbr></nobr>/bin/tcsh eddie<nobr> <wbr></nobr>/bin/csh billy<nobr> <wbr></nobr>/bin/zsh}


  To see what shell eric has just use:


  puts $usershell(eric).


  See the TCL example is 20% shorter than the perl example. The line is almost self explanitory, You've set an array, how much simpler could that be? You will find your TCL scripts are usually 20% - 50% shorter in TCL, which means less typing, less debugging, and quicker script creation. NOTICE also that TCL commands don't have a ';' at the end of each line, as TCL is smart enough to be able to figure out where the line ends without one.

I've found that for my day to day tasks TCL works better. It's not as cryptic as perl, and it's easier for me. The two things I like best about TCL is (1) The Expect extention, (2) tclsh. Tclsh is a stripped down shell that you can type commands in for example:

rm@linuxsystem:~$ tclsh
% % array set usershell {jimi '/bin/bash' eric '/bin/tcsh' eddie '/bin/csh' billy '/bin/zsh'}
% puts $usershell(jimi)
'/bin/bash'

This allows me to evaluate or test some subroutines in a shell environment before sticking them in a script. My advice is to find what works for you. You've got Perl, TCL, Python, Ruby, Bash, CSH, and probably one or two I forgot to mention.

#

Re:you're not a sysadmin if...

Posted by: Administrator on August 05, 2004 01:50 AM
First of all, who said you can't do sysadmin work without Perl? For somebody only knowning enough Perl to read other scripts, you're pretty arrogant about how much better TCL is than Perl. As the other reply demonstrated, you are comapring apples to oranges and I can tell you from experience, TCL and Perl and CF, and C, and... are all pretty nice languages. I've written some very useful tools in all of them.



And by that, TCL is in no way going to create a comparable script at 20%-50 smaller code size. I can tell you this, you are not a sysadmin if you stick to a single language to solve all of your day to day problems. Two things I love about Perl, DB access and RegEx.



Go do your homework before coming to a Perl article and pissing all over it.

#

Get it right!

Posted by: Administrator on July 08, 2004 09:20 PM

It is never ever PERL.

It is perl for the interpreter.

It is Perl for the language.

#

This story has been archived. Comments can no longer be posted.



 
Tableless layout Validate XHTML 1.0 Strict Validate CSS Powered by Xaraya