Tuesday, January 11, 2011

20 Perl Tips And Tricks

Perl is full of secrets that can make your life as a Perl programmer easier - if you know about them. In this article I present a handful of Perl tips and tricks that some Perl programmers may not have come accross and may find useful.

1) Want to know what OS you are running under?
Check the $^O variable. Under Windows it may contain "MSWin32", under Linux it simply contains "linux".

2) Want to know how long your script has been running to the nearest second? $^T contains the time your script started, so simply subtract it from the current time.

$runningfor = time - $^T;
Note that this is only accurate to the nearest second, so it is not much use for short lived scripts.

3) Need a fast way of getting rid of the second half of an array? Simply divide $#array by two, where array is the name of the @array.
$#array /= 2;
Naturally, other arithmetic operations on $#array will work too.

4) A quick way to set a variable to a default value if it evaluates to false is to use the ||= operator.
$color ||= 'black';
Will set $color to black if it is empty, undefined or contains zero. Otherwise it will retain its original value.

5) Ever fancied a one-liner to dump a hash?
print "$_ = $hash{$_}\n" for (sort keys %hash);
If you don't care whether the hash keys are sorted, remove the sort keyword. 

6) Want to assign to the next available value of an array? Evaluating an array in scalar context gives the number of elements in the array, and as arrays are base 0 you can write:-
$array[@array] = 'What to add';
Alternatively, this could be done using push:
push @array, 'What to add';
Which is more readable.

7) Want to use warnings, but have some code that won't run under the pragma? Simply turn them off for that bit of code by putting:-
no warnings;
To turn them back on, just put "use warnings;" again. This works for other pragmatic modules, including "strict".

8) You can check the syntax of your script at the command line by typing:-
perl -c yourscript.pl


9) Need to give Perl a hint about where your module files might be? Simply do this:-
use lib '/home/mymodules';


10) When doing a pattern match, you sometimes want to use brackets to group things, but prevent them from capturing. The capturing can be stopped by putting ?: after the opening bracket, e.g.
/a (?:black|grey|white) cat/


11) When you bind a variable to a substitution, the expression as a whole will return the number of substitutions made, e.g.
$replacements =$myvar =~s/foo/bar/g;


12) Want to count the number of times $word appears in $text?
my $numtimes = 0;
$numtimes++ while ($text =~ /\b $word \b/gx));


13) Want to make a table of the number of times each word in $text appears?
my %words = ();
$words{lc($_)}++ for $text =~ /\b([\w']+)\b/g;
Each key of the %words hash will be a word in $text, and the value is the number of times that word appeared.

14) Does your pattern look like an unreadable mess?
Use the x modifier and you can put spaces, newlines and comments in your pattern, and they will be ignored when the pattern is compiled.

15) Turn "ThisTextWithoutSpaces" into "This Text Without Spaces" like this:-
$text =~ s/([a-z])([A-Z])/$1 $2/g;


16) Look up the documentation on a Perl module (those installed on your system) at the command line using the perldoc command, e.g.
perldoc CGI


17) If you are doing many pattern matches on a particular string, you may be able to improve performance by having Perl study the string first, e.g.
study $string;
Now do lots of pattern matches on $string...[/code]

Another optimisation if your pattern contains a variable that will remain constant is to add the "o" modifier, which only compiles the pattern the first time it is matched.

18) Get the size of a file in bytes quickly like this:-
$size = -s "path/to/file.txt";

19) Running Windows? Got a file with UNIX line endings? Let Perl lend you hand. Drop to the console and put:-
perl -ne "s/\n/\r\n/; print;" Original.txt > Fixed.txt

Using appropriate file names.

20) Got a chunk of obfuscated or just plain messy and hard to read Perl code? The Deparse module may be able to help. It compiles, then decompiles the program it is given, expanding it out and formatting it nicely. To run it at the command line, type "perl -MO=Deparse prog.pl". Here is an example of its usage, showing the input program (red) and the output of Deparse (blue).
$ cat scary.pl
for(74,117,115,116){$::a.=chr};(($_.='qwertyui')&&
(tr/yuiqwert/her anot/))for($::b);for($::c){$_.=$^X;
/(p.{2}l)/;$_=$1}$::b=~/(..)$/;print("$::a$::b $::c hack$1.");
$ perl -MO=Deparse scary.pl
foreach $_ (74, 117, 115, 116) {
    $a .= chr $_;
}
;
$_ .= 'qwertyui' and tr/eiqrtuwy/nr oteah/ foreach ($b);
foreach $_ ($c) {
    $_ .= $^X;
    /(p.{2}l)/;
    $_ = $1;
}
$b =~ /(..)$/;
print "$a$b $c hack$1.";

No comments: