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

Perl test comparison methods

use Test::More tests => 23;
# or
use Test::More qw(no_plan);
ok($got eq $expected, $test_name);
like ($got, qr/expected/, $test_name);
is_deeply($got_complex_structure, $expected_complex_structure, $test_name);
Compare data structures
eq_or_diff $got, $expected, "description"
Test::Lazy
No descriptions required
# Will evaluate the code and check it:
try('qw/a/' => eq => 'a');
# Don't evaluate, but still compare:
check(1 => is => 1);

Everybody do the DBI

  use DBI;

@driver_names = DBI->available_drivers;
%drivers = DBI->installed_drivers;
@data_sources = DBI->data_sources($driver_name, \%attr);

$dbh = DBI->connect($data_source, $username, $auth, \%attr);

$rv = $dbh->do($statement);
$rv = $dbh->do($statement, \%attr);
$rv = $dbh->do($statement, \%attr, @bind_values);

$ary_ref = $dbh->selectall_arrayref($statement);
$hash_ref = $dbh->selectall_hashref($statement, $key_field);

$ary_ref = $dbh->selectcol_arrayref($statement);
$ary_ref = $dbh->selectcol_arrayref($statement, \%attr);

@row_ary = $dbh->selectrow_array($statement);
$ary_ref = $dbh->selectrow_arrayref($statement);
$hash_ref = $dbh->selectrow_hashref($statement);

$sth = $dbh->prepare($statement);
$sth = $dbh->prepare_cached($statement);

$rc = $sth->bind_param($p_num, $bind_value);
$rc = $sth->bind_param($p_num, $bind_value, $bind_type);
$rc = $sth->bind_param($p_num, $bind_value, \%attr);

$rv = $sth->execute;
$rv = $sth->execute(@bind_values);
$rv = $sth->execute_array(\%attr, ...);

$rc = $sth->bind_col($col_num, \$col_variable);
$rc = $sth->bind_columns(@list_of_refs_to_vars_to_bind);

@row_ary = $sth->fetchrow_array;
$ary_ref = $sth->fetchrow_arrayref;
$hash_ref = $sth->fetchrow_hashref;

$ary_ref = $sth->fetchall_arrayref;
$ary_ref = $sth->fetchall_arrayref( $slice, $max_rows );

$hash_ref = $sth->fetchall_hashref( $key_field );

$rv = $sth->rows;

$rc = $dbh->begin_work;
$rc = $dbh->commit;
$rc = $dbh->rollback;

$quoted_string = $dbh->quote($string);

$rc = $h->err;
$str = $h->errstr;
$rv = $h->state;

$rc = $dbh->disconnect;

Bash menu

Try this menu script for bash scripts:

while getopts ":u:a:s:v" options; do
  case $options in
    u ) uname=$OPTARG;;
    a ) attrs=$OPTARG;;
    s ) searchattr=$OPTARG;;
    v ) att=ALL;;
    h ) echo $USAGE;;
    \? ) echo $USAGE
         exit 1;;
    * ) echo $USAGE
          exit 1;;
  esac
done

echo uname = $uname

Test scripts

Even a set of test scripts often benefit from modularised separate libraries, configuration files and dedicated data files. And logging.

Importing a module's namespace in Perl

Ever get this error for a module you've written?

Use of inherited AUTOLOAD for non-method X() is deprecated

Put this at the top of your module:

package My::Module;

use Exporter;
our @ISA = 'Exporter';
our @EXPORT = qw(put the methods here);

And then in the main program:

use My::Module qw( the methods to import );

keywords: export import exporting

Bash variable comparisons

...bash logic...

Note that integer and string comparison use a different set of operators.
integer comparison
-eq
is equal to
if [ "$a" -eq "$b" ]
-ne
is not equal to
if [ "$a" -ne "$b" ]
-gt
is greater than
if [ "$a" -gt "$b" ]
-ge
is greater than or equal to
if [ "$a" -ge "$b" ]
-lt
is less than
if [ "$a" -lt "$b" ]
-le
is less than or equal to
if [ "$a" -le "$b" ]
<
is less than (within double parentheses)
(("$a" < "$b"))
<=
is less than or equal to (within double parentheses)
(("$a" <= "$b"))
>
is greater than (within double parentheses)
(("$a" > "$b"))
>=
is greater than or equal to (within double parentheses)
(("$a" >= "$b"))

string comparison
=

is equal to
if [ "$a" = "$b" ]
==
is equal to
if [ "$a" == "$b" ]
This is a synonym for =.

Set file modes in Perforce

Perforce.

Edit a file and:
  • explicitly set RCS keywords to be expanded (k)
  • have the executable bit set (x)
  • always be writeable on the client (w)
p4 edit -t text+kxw

or if it's already being edited:

p4 reopen -t text+kxw

See also

p4 help filetypes

+w always writable on client
+x exec bit set on client

+k $Keyword$ expansion of Id, Header, Author, Date, DateTime, Change, File, Revision
+ko $Keyword$ expansion of Id, Header only
+l exclusive open: disallow multiple opens

[full article]

Shortcuts in Firefox 2

You can set up a shortcut keyword by
  1. going to the properties of a bookmark in 'organize bookmarks',
  2. putting a %s as the wildcard in the URL
  3. setting a keyword for the shortcut
Then you can type the keyword and a wildcard in the address bar to load that url.

[full article]

Make Firefox 3 look like Firefox 2

From the neo-luddite department.

Perforce commands

p4 sync -f ./...
p4 diff -f [file]
p4 filelog -l -i -t [file] // complete history (-l = long text, -i = follow branches, -t = include times)
p4 annotate [file] // show file with changes marked

Tagging

// NOTE: If no revision specified, the head revision will be tagged
p4 tag -l ProjectName_R01 [filename]#revision // tag a specific revision of a file.

p4 files @ProjectName_R01 // list files on a tag

vi command

When tabs are automatically converted to spaces:

:set tabstop=4
:set expandtab

To insert a hard tab:

Ctrl-V, [tab]

How to use encoding

Encoding is necessary only for transmission of data.
Any data stored in files or a database should never be encoded.

Get the transmission right (decode 'automatically' as part of the receiving process, as soon as possible after receiving the data) and you'll never need to worry about decoding issues.

Regular expressions in vi

Keep the first character of a line, but then insert an 'A':

s/^\(.\)/\1A/

NOTE: parentheses and the plus sign must be escaped.

Freeing memory in C

If you allocate memory in a subroutine for a variable that you then return, you’ve got to free the variable you return:
 
char * allocstring(char * text)
{
    char * s = malloc(s, strlen(text)+1);
    strcpy(s, text);
    return s;
}
 
void main()
{
    char * s = allocstring(“Hello World”);
    free(s);
}

Regular expressions in C: Advice

If you can avoid using regular expressions in C, then *do not use them!!*

Instead try the strstr (find substring) and strtok (like perl's split) routines.