Thursday, October 18, 2012

perl is beautiful - part 2

We've seen how perl can be used, but you may be wondering, so what? Fasten your seatbelt, for fun begins now.

Interpreter switches

The single most useful tool I'm going to show you. The interpreter accepts many parameters, which alter the way it runs, but most importantly, they can alter the way the code is executed. First, though, I'll show you the -e switch, which will be used on all the other examples.
$ perl -e 'print "hello\n";'
The switch tells the interpreter that, instead reading from stdin or from a file, the program will be contained inside the next argument. Note that,  by perl's definition, you don't need to use a semicolon after the last (here also the only) command. But I've included it to avoid confusion on the quotes. With this switch, it will be easier to show you the others.

Let's start with -n, which will surround your code with the following construct:
while(<>) {
    # your code
}
Try running our previous example but adding this switch. It will start listening on stdin, and after every line it will print the string 'hello' (I call it the nice program). One thing to note is that the -e switch and the program string must be contiguous. You can run the program like the first three lines below, but the fourth will give you an error:
$ perl -ne 'print "hello\n"'
$ perl -n -e 'print "hello\n"'
$ perl -e 'print "hello\n"' -n
$ perl -e -n 'print "hello\n"' # This is wrong!
But what really happened when we ran that program? If you remember the last post, <> is the input operator. So, "while(<>)" means "read lines from the input until it ends". And if you have really good memory (or are already tainted by the perl way of thinking), you'll remember that the input read will go to the variable $_. We can test it with our reimplementation of cat:
$ perl -ne 'print'
See what I did there? I tested your memory again.$_ is used as the default argument to many functions in perl, including print. This allows you to say just "print" here, instead of "print $_". And this code is such a common occurrence that perl already has another switch to do just that: -p.

$ perl -pe ''
Running this, you can see that it is exactly the same as the previous. Just like -n, it surrounds your code with more code, but it adds a little something to what -n adds:
while(<>) {
     # your code
     print
}

Regular expressions revisited

Now, this is already fun. We can make a program that does anything to each line of input (like using ssh -Y, a list of swear words and notify-send on your coworker's computer). But the real power of what I'm showing you comes from combining these techniques with perl's humongous power. Check this:
$ perl -ne 'print if m/=D/'
This will print every happy line on a file. Remember that the default parameter for the m// operator is also $_ (isn't it beautiful?). If you followed me all the way here, you can now start applying it, just by remembering this simple command line. Quick example I use every day: find all python functions on a file. 
$ perl -ne 'print if m/^\s*def /'
From here,  you can go anywhere. The nice thing is now you have the power of a real programming language, and can do all the bizarre things perl can do (and it can do some really bizarre things).One thing that took me a little time to get used to was the "boilerplate" part of the command line. But after I used it a few times, it's now natural, I don't even have to think about it. And it took only a couple of seconds to google "perl command line" anyway (at some point, I only had to type "perl" on firefox's address bar and it would show me the page right away).

Coming next: on the last post on this (unexpectedly long) topic, I'll show you some (kind of ) advanced perl and regexp techniques.

No comments:

Post a Comment