Stupid Perl mistake

While messing around with Perl I ran into the following error:

$ perl -e ‘use Time::Local print (localtime)[5] + 1900;’
syntax error at -e line 1, near “)[”
Execution of -e aborted due to compilation errors.

I asked Perl guru Peter Marschall if he knew what was wrong with this statement, and Peter mentioned that ‘print’ is trying to use the ‘(‘ and ‘)’ to enclose it’s argument list (which is not applicable here). Since I am still learning Perl, I don’t feel bad making mistakes (I am learning lots!)!

Optimizing Perl code (localtime)

While updating some Perl code I wrote quite some time back, I came across the following:

my ($sec, $min, $hour, $day, $month, $year, $wd, $day, $dst) = localtime(time);
print $year + 1900 . “\n”;

This code is rather wasteful, especially when the program only needs the year. A much simpler solution is to put the localtime() result into array context, and index into it:

$year = (localtime)[5] + 1900;
print “$year\n”;

I am currently reading two Perl books, and it amazes me just how versatile Perl is!

Perl and greediness

When a regular expression uses the ‘*’ wild card operator to match text, the regular expression will attempt to match as much as possible when applying the regular expression. Given the the following Perl code with the regular expression “(Some.*text)”:

$ cat test.pl

#!/usr/bin/perl 

my $string = "Some chunk of text that has text";

$string =~ /(Some.*text)(.*)/;
print "One: $1\nTwo: $2\n";

We see that by default Perl will match from the word “Some” to the right-most word “text.”:

$ test.pl
One: Some chunk of text that has text
Two:

In regular expression parlance, this is considered a “greedy” regular expression since it attempts to match as much as possible. This is not ideal in most situations, and is easily fixed with Perl’s ‘?’ operator:

$ cat test.pl

#!/usr/bin/perl 

my $string = "Some chunk of text that has text";

$string =~ /(Some.*?text)(.*)/;
print "One: $1\nTwo: $2\n";

$ test.pl
One: Some chunk of text
Two:  that has text


In this example Perl will no longer become greedy when evaluating the expression, and will attempt to match up to the left-most occurence of the string element prefaced by ‘?’. Regular expressions are amazingly cool, but sometimes it feels like witchcraft when developing the right regex incantation to solve complex problems.

Generating random passwords with Perl

While performing some house cleaning this evening, I came across the following Perl nugget:

#!/usr/bin/perl

my @alphanumeric = ('a'..'z', 'A'..'Z', 0..9);
my $randpassword = join '', map $alphanumeric[rand @alphanumeric], 0..8;
print "$randpassword\n"

This awesome little 3-line script will produce random 8-character alphanumeric passwords:

$ randpasswd.pl
ahvtGRE6U

$ randpasswd.pl
lxVLA7xLv

I wish I knew where I grabbed this from so I could publicly thank the author.

Perl version of stat

While messing around with Perl, I created a Perl program that displays output similar to the Linux stat utility:

$ stat.pl /etc/services /etc/passwd /etc/shadow

  File: /etc/services
  Size: 15           Blocks: 2                Block Size: 8192
Device: 22282240     Inode: 7876              Links:    1
 Perms: 777          Uid: ( 0 / root )        Gid: ( 0 / root )       
Access Time (mtime)      : Tue Sep 13 18:48:34 2005 
Change Time (ctime)      : Mon Aug 15 22:48:37 2005 
Modification Time (mtime): Mon Aug 15 22:48:37 2005 

  File: /etc/passwd
  Size: 725          Blocks: 2                Block Size: 8192
Device: 22282240     Inode: 9021              Links:    1
 Perms: 644          Uid: ( 0 / root )        Gid: ( 0 / root )       
Access Time (mtime)      : Tue Sep 13 18:50:51 2005 
Change Time (ctime)      : Tue Aug 16 00:25:09 2005 
Modification Time (mtime): Tue Aug 16 00:25:09 2005 

  File: /etc/shadow
  Size: 376          Blocks: 2                Block Size: 8192
Device: 22282240     Inode: 10176             Links:    1
 Perms: 400          Uid: ( 0 / root )        Gid: ( 0 / root )       
Access Time (mtime)      : Tue Sep 13 18:50:51 2005 
Change Time (ctime)      : Tue Aug 16 00:25:18 2005 
Modification Time (mtime): Tue Aug 16 00:25:18 2005 

This will be a useful little utility once I cleanup the Perms and Device lines. :)