Wednesday, August 6, 2008

Oneliners

A short example
You'll have noticed Perl packs a lot of power into a small amount of code. You can feed Perl code directly on the command line. This is known as a oneliner, for obvious reasons. An example:
perl -e"for (55..75) { print chr($_) }"

The -e switch tells Perl that a command is following. The command must be enclosed in doublequotes, not singles as on Unix. The command itself in this case simply prints the ASCII code for the number 55 to 75 inclusive.



File access
This is a simple find routine. As it uses a regex, it is infinitely superior to NT's findstr :
perl -e"while (<>) {print if /^[bv]/i}" shop.txt

Remember, the while (<>) construct will open whatever is in @ARGV . In this case, we have supplied shop.txt so it is opened and we print lines that begin with either 'b' or 'v'.
That can be made shorter. Run perl -h and you'll see a whole list of switches. The one we'll use now is -n , which puts a while (<>) { } loop around whatever code you supply with -e . So:

perl -ne"print if /^[bv]/i" shop.txt

which does exactly the same as the previous program, but uses the -n switch to put a while (<>) loop around whatever other commands are supplied.
A slightly more sophisticated version:

perl -ne"printf \"$ARGV : %3s : $_\",$. if /^[bv]/i" shop.txt

which demonstrates that doublequotes must be escaped.



Modifying files with a oneliner and $^I
If you don't remember $^I then please review the section on Files before proceeding. When you're ready, copy shop.txt to shop2.txt .

perl -i.bk -ne"printf \"%4s : $_\",$." shop2.txt

The -i switch primes the inplace edit operator. We still need -n .
If you had a typical quoted email message such as:

>> this is what was said
>> blah blah
> blaaaaahhh

The new text

and you wanted to remove the >, then:
perl -i.bk -pe"s/^>+ ?//" email.txt

does the trick. Regex recap -- the caret matches what follows to the beginning of the string, the + means one or more (no, we do not use * which means 0 or more), then we will match one space with \s , but it is not necessary for the space to be there for the match to be successful, hence ? .

What is new in terms of oneliners is the use of -p , which does exactly the same thing as -n except that it adds a print statement too. In case you were wondering why the previous example used -n and this one uses -p -- the previous example uses prints data with printf, whereas this example doesn't have an explicit print statement so we provide one with -p .

Some other useful oneliners -- a calculator and a ASCII number lookup:

perl -e"print 50/200+2"
perl -e"for (50..90) { print chr($_) }"

There are plenty more oneliners, and they are an essential part of any sysadmin's toolbox. The two examples below are functionally equivalent but the lower one is perhaps a little more readable:
perl -e"for $i (50..90) { print chr($i),\" is $i\n\" }"

perl -e"for $i (50..90) { print chr($i),qq| is $i\n| }

Whatever follows qq is used as a delimiter, instead of having to escape the backslash. I learnt this from the Perl-Win32-Users mailing list (see top) - I think it was Lennart Borgman who pointed it out. He also mentioned that you don't need the closing doublequote. Saves a little typing.

No comments: