A piggy bank of commands, fixes, succinct reviews, some mini articles and technical opinions from a (mostly) Perl developer.

Regex anchors in Perl

A lot of the time it seems that Perl programmers write a regex like

/^foo$/

(where “foo” is some arbitrary regex pattern)

but from the context it seems like the intention of the programmer was to make it so that the string to be searched must match the pattern “foo”, and there must be nothing between the beginning of “foo” and the beginning of the string to be searched, and there must be nothing between the end of “foo” and the end of the string to be searched.

But of course the regex doesn’t do that.

The metacharacter ‘$’ matches not only at the end of the string to be searched but also just before a newline character at the end of the string to be searched. (Of course when the ‘m’ flag is specified, ‘$’ behaves differently. But I’d like to concentrate on the behaviour without the ‘m’ flag for the time being.)

So the above pattern will match “foo” and “foo\n”.

Is that what the programmer really wanted? I think in many cases not.

So how can we make the pattern match exactly at the end of the string to be searched?

The answer is to use the metacharacter ‘\z’. This matches exactly at the end of the string to be searched.

So to make a regex that matches the pattern “foo”, and with the beginning and end of the pattern bound to the end of the string to be searched, we could write:

/^foo\z/

=====
Here endeth the bit about doing the minimum to make the code correctly reflect the intention of the programmer. The rest is about style, personal preference, readability, etc.
=====

Some might say that using ‘^’ to match the beginning of the string to be searched and ‘\z’ at the end is a bit dicey because the meaning of ‘^’ is changed if the ‘m’ flag is used but the meaning of ‘\z’ isn’t. It would be nice if there was a metacharacter which exactly matched the beginning of the string to be searched, regardless of the ‘m’ flag. Fortunately there is, ‘\A’. Using that would give:

/\Afoo\z/

But because ‘\A’ ends with a letter, the regex can be a bit hard to parse if the ‘\A’ is followed by a pattern which begins with a letter. So some might say that it might be a good idea to use the ‘x’ flag to allow whitespace inside the regex. That would give

/ \A foo \z /x

Though I find it a bit hard to read when slash delimiters are combined with a few initial-backslash metacharacters, so I prefer to use a different delimiter. So I would think to use something like:

m{ \A foo \z }x

- by Bill Blunn
See also http://perldoc.perl.org/perlre.html#Regular-Expressions

Parameter checking Perl


use MooseX::Params::Validate;
use MooseX::Types::Moose qw{ ArrayRef Int };
use MooseX::Types::Structured qw{ Dict };
use MooseX::Types::Common::Numeric qw{ PositiveInt PositiveOrZeroInt };
use MooseX::Types::Common::String qw{ NonEmptyStr };

sub some_method {
    my ($self, $channel_id, $some_array_of_structs) = validated_list(
        \@_,
        channel_id   => { isa => PositiveInt },
        channel_name => { isa => NonEmptyStr },
        some_array_of_structs => {
            isa => ArrayRef[ Dict[
                some_id    => PositiveInt,
                quantity   => PositiveOrZeroInt,
                cruciality => Int
            ] ]
        }
    );
    # ...
}

Fix hanging network-manager applet in Ubuntu 11.04

#!/bin/bash

# Fix the frozen network-manager applet
# Thanks to http://askubuntu.com/questions/23611/network-manager-applet-menu-freezes-and-does-not-respond

killall nm-applet
sudo /etc/init.d/network-manager restart
nm-applet &> /dev/null &

Table parsing, old friend

Some comments I found in code once:

    # Table parsing, old friend... We have spent many long evenings together,    
    # working through your broken tables, talking about your issues with         
    # implicit thead elements, and your quirky tr/th heuristics. But ... but     
    # but it's time for us to move on. We can't keep doing this. It's not you,   
    # it's me...                                                                 
    #                                                                            
    # I've ... I've met someone new. She's beautiful, she's modern, and she's    
    # elegant. She's logical, she's clean, and she's well-structured, if you     
    # know what I mean...                                                        
    #                                                                            
    # She always puts a single tr in her thead's, and what's more, she's always  
    # got a thead. Her tbody's support her tr's, and she never forgets them.     
    # Life is simpler now. Better. Less miscommunication, fewer arguments over   
    # what defines a header row. Sometimes it lasts in parsing code, but         
    # sometimes, it hurts instead...                                             
    #                                                                            
    # IF YOU EXTEND THIS CODE TO SUPPORT YOUR BROKEN HTML
    # TABLES I WILL FIND YOU. YOU HAVE BEEN WARNED!  

Thanks to Pete for much amusement.

How to implement a link table in DBIC

# Define many-to-many relationship between foo and bar tables
# using the foos_bars linking table

# in the database:


TABLE foo ( id INTEGER, something TEXT );
TABLE bar ( id INTEGER, another_thing TEXT );
TABLE foo_bar ( foo_id INTEGER, bar_id INTEGER );


# in Result/Foo.pm:

__PACKAGE__->many_to_many(
    'bars', # name of the relationship you're creating in foo
    'foos_bars', # name of the relationship in foo that points to the link table
    'bar' # name of the relationship to bar on the link table
);


# in some nearby code:

@bars = $foo->bars;


CPAN docs

Shuffle lines in bash

#!/bin/bash
# Print out the lines from a file, in a random order
FILE=$1
if [[ -z $FILE ]]
then
    echo "usage: shuffle [filename]"
    exit 1
fi
for i in `cat $FILE`; do echo "$RANDOM $i"; done | sort | sed -r 's/^[0-9]+ //'

Thanks

Display postgres enum values

  • To see all enums:
select n.nspname as enum_schema,  
    t.typname as enum_name,
    string_agg(e.enumlabel, ', ') as enum_value
from pg_type t 
    join pg_enum e on t.oid = e.enumtypid  
    join pg_catalog.pg_namespace n ON n.oid = t.typnamespace
group by enum_schema, enum_name;
thanks, StackOverflow

  • To see one enum:
SELECT enumlabel  FROM pg_enum WHERE enumtypid = 'your_enum_here'::regtype;

Use variables with Postgres, just like MySQL

It's a little more difficult than MySQL, as you have to create a function to contain the logic:

DROP FUNCTION get_column(integer);
CREATE FUNCTION get_column(row_id integer) RETURNS text AS $$
DECLARE
    t1_row foo%ROWTYPE;
BEGIN
    SELECT * INTO t1_row FROM foo WHERE foo.status != 'closed' limit 1;
    RETURN t1_row;
END;
$$ LANGUAGE plpgsql;

SELECT get_column(3);