The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/perl

use ddb;
use Fcntl qw(:seek);

# defaults
$show_step	= 100;
$col_delim	= qr(\s+);
$row_delim	= "\n";
$key_type	= 'a*';
$val_type	= 'a*';
$hash_size	= 104729;
$quiet		= 0;

sub usage {
  print STDERR join '',
    "Usage:\n",
    "	$0 [options ...] file.ddb\n",
    "Options:\n",
    "	[-k:type]              # default type $key_type\n",
    "	[-v:type]              # default type $val_type\n",
    "	[-t col_delim]         # default \\s+\n",
    "	[-n row_delim]         # default \\n\n",
    "	[-s show_step]         # default 100\n",
    "	[-c hash_size]         # default 104729\n",
    "	[-q]                   # quiet\n",
    ;
  exit 1;
}

@ARGV or usage;
my $db_filename = pop(@ARGV);
-e "$db_filename.meta" and do "$db_filename.meta";

while ($ARGV[0] =~ /^-(.*$)/) {
  my $opt = $1;
  shift(@ARGV);

  $opt eq '-' and last;

  if ($opt =~ /^k:(.+$)/) {
    $key_type = $1;
    next;
  }

  if ($opt =~ /^v:(.+$)/) {
    $val_type = $1;
    next;
  }

  if ($opt =~ /^t(.*$)/) {
    $col_delim = $1 || shift(@ARGV) or usage;
    $col_delim = qr/$col_delim/;
    next;
  }

  if ($opt =~ /^n(.*$)/) {
    $row_delim = $1 || shift(@ARGV) or usage;
    next;
  }

  if ($opt =~ /^s(.*$)/) {
    $show_step = $1 || shift(@ARGV) or usage;
    next;
  }

  if ($opt =~ /^c(.*$)/) {
    $hash_size = $1 || shift(@ARGV) or usage;
    next;
  }

  if ($opt eq 'q') {
    $quiet = 1;
    next;
  }

  usage;
}

@ARGV and usage;

my $db = tie %db, ddb, $db_filename, $hash_size or die "$0: $db_filename: $!\n";

local $/ = $row_delim;
my $count = 0;
select(STDOUT);
$| = 1;

eval {
  while (<STDIN>) {
    chomp;
    my @col = split /$col_delim/;
    my $k = pack($key_type, @col);
    my $kv = pack($key_type . $val_type, @col);
    my $v = substr($kv, length($k));

    $db{$k} = $v;

    ++$count;
    $quiet or $count % $show_step or print STDERR "$0: $count records\r";
  }
};

$quiet or print STDERR "$0: $count records\r\n";

untie %db;
$@ and die $@;
exit 0;