Random Perl Tricks

Here's some random useful tricks with Perl, which aren't long enough to warrant their own pages.

Find longest entry in array

A quick way to find the length of the longest value in an array:

my @array = ('foo', 'bar', 'badger', 'wibble');
my $longest = (reverse sort { $a <=> $b } map { length($_) } @array)[0];

(Basically for every item in @array, the map block returns the length (in chars), which the sort then sorts in reverse numeric order (so highest first), and the we then take the first item in the resulting array. Elegant eh?)

This could also be done using List::Util::max(), as suggested by “Spoon Reloaded”:

use List::Util (max);
my @array = ('foo', 'bar', 'badger', 'wibble');
my $longest = max (map { length } @array)

As always, TIMTOWTDI :)

Sort hash by values

Getting a list of hash keys, sorted by their values:

my %hash = (foo => 5, bar => 2, badger => 10);
my @sorted_keys = sort { $hash{$a} <=> $hash{$b} } keys %hash;
# that will return the keys, sorted by the value in numerical ascending order.  
# To change to reverse (descending) order, just swap the $a and $b.
# To sort strings instead of numerically, use ''cmp'' instead of ''<=>''.

Validating email addresses

Just about every programmer out there, at one time or another, will try to write code to validate an email address. Don't. If you haven't read and understood RFC822, any attempt at validation you write will reject valid addresses. If you have read and understood all of RFC822, you should probably consider validating your social life instead of email addresses.

Just use something like Email::Valid to do the hard work for you:

use Email::Valid;
if (Email::Valid->address( $email )) {
	# it's valid

Email::Valid can also do some other funky tricks, including fixing up the email address to automatically correct some common typos, performing MX checks to further check that the address seems valid etc.

Or, use Mail::RFC822::Address :

use Mail::RFC822::Address qw(valid validlist);
if (valid("bob@example.com")) {
    print "That's a valid address\n";
if (validlist("bob@example.com, jenny@example.net")) {
    print "That's a valid list of addresses\n";
# or, don't import the valid() / validlist() methods and use the
# full names, this makes it nice and obvious where they come from
# and what's doing the validation:
if (Mail::RFC822::Address::valid($email)) {
    print "Yup, valid\n";

If you still want to write your own regular expression to validate email addresses, take a look at the hairy regular expression on http:www.ex-parrot.com/~pdw/Mail-RFC822-Address.html - are you really sure? Just grab Email::Valid from CPAN at http:search.cpan.org/~rjbs/Email-Valid/ or Mail::RFC822::Address from http:search.cpan.org/~pdwarren/Mail-RFC822-Address/ - either of these will do the job nicely. There's no point re-inventing the wheel, especially a wheel this hairy and fraught with cunning traps and details that you'll never quite fully cover. ===== Quickly mask card numbers ===== <code perl> # using substr as an lvalue to assign to: substr($card, 0, -4) = '*' x (length($card)-4); # or putting it in a new var: my $masked = ('*' x (length($string)-4)) . substr $string, -4; </code> ===== Stripping accented (extended ASCII) chars ===== OK, this one is Very Bad, and you shouldn't do this. Really. You should use Unicode. But, I needed this for creating a CSV file (which, according to Text::CSV at least, can only contain standard ASCII chars), so: This will replace accented chars (e.g. é) with a standard letter. <code perl> sub plainascii { my $in = shift; $in =~ tr/áéëèíîóöøúüñç/aeeeiiooouunc/; return $in; } </code> ===== Quick code timing ===== A quick way to time blocks of code: <code perl> use Time::HiRes; my $start_time = [Time::HiRes::gettimeofday]; # do some stuff here my $elapsed = Time::HiRes::tv_interval($start_time); # elapsed will be number of seconds, e.g. 5.161256 </code>

perl/tricks.txt · Last modified: 2010/02/26 10:45 (external edit)
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki