Cuando Perl se instala en un sistema proporciona una pasarela a las librerías C que dan soporte a DBM (y a la librería SDBM que se encuentra en la distribución de Perl).
Las DBM tienen una limitación: sólo se pueden almacenar pares clave-valor escalares. No es posible almacenar estructuras de datos complejas.
La función dbmopen nos permite crear hashes persistentes.
Veamos el siguiente ejemplo dbm.pl
que utiliza un hash DBM
para almacenar una gramática:
lhp@nereida:~/Lperl/src$ cat -n dbm.pl 1 #!/usr/bin/perl -w 2 use strict; 3 my %DATA; 4 5 dbmopen(%DATA, "my_gramma", 0644) or die "can not create my_gramma $!"; 6 $DATA{TOKENS} = "+|-|/|*|(|)|num"; 7 $DATA{START} = "E"; 8 $DATA{E} = "E+T|E-T"; 9 $DATA{T} = "T*F|T/F"; 10 $DATA{F} = "(E)|num";
$DATA{TOKENS}
contiene los terminales de la gramática, $DATA{START}
el símbolo de arranque y $DATA{A}
contiene las reglas de producción de la variable
sintáctica A
.
Antes de la ejecución de dbm.pl
tenemos dos programas Perl dbm.pl
y
dbm2.pl
en nuestro directorio:
>ls -l -rwxrwx--x 1 pl users 194 Mar 10 08:44 dbm.pl -rwxrwx--x 1 pl users 300 Mar 10 09:54 dbm2.pl
Después de la ejecución de dbm.pl
aparecen dos nuevos ficheros que contienen
las claves y valores del hash persistente:
>ls -l -rwxrwx--x 1 pl users 194 Mar 10 08:44 dbm.pl -rwxrwx--x 1 pl users 300 Mar 10 09:54 dbm2.pl -rw-r----- 2 pl users 12333 Mar 10 10:54 my_gramma.pag -rw-r----- 2 pl users 12333 Mar 10 10:54 my_gramma.dir
Veamos ahora otro programa que usa el hash persistente:
lhp@nereida:~/Lperl/src$ cat -n dbm2.pl 1 #!/usr/bin/perl -w 2 use strict; 3 my %G; 4 dbmopen(%G, "my_gramma", 0644) or die "can not create my_gramma $!"; 5 6 my $tokens = $G{TOKENS}; 7 my @tokens = split('\|',$tokens); 8 9 print "TOKENS: "; 10 { 11 local $" = ','; 12 print "@tokens\n"; 13 } 14 15 my $start = $G{START}; 16 print "$start -> $G{$start}\n"; 17 18 for my $k (sort keys %G) { 19 print "$k -> $G{$k}\n" if ($k !~ /(START)|(TOKENS)|($start)/); 20 }Al ejecutarlo obtenemos esta salida:
> dbm2.pl TOKENS: +,-,/,*,(,),num E -> E+T|E-T F -> (E)|num T -> T*F|T/F
Una alternativa a dbmopen es usar el módulo DB_File. El siguiente ejemplo muestra como usarlo:
$ cat -n testdbfile.pl 1 #!/usr/local/bin/perl -w 2 use strict; 3 use DB_File; 4 my $file = shift || 'test'; 5 my %h; 6 tie (%h, 'DB_File', $file) or die $!; 7 8 $h{abc} = "ABC"; $h{def} = "DEF"; $h{ghi} = "GHI"; 9 untie (%h); 10 11 my %g; 12 tie (%g, 'DB_File', $file) or die $!; 13 14 print "$_ => $g{$_}\n" for keys %g; 15 16 untie(%g);
al ejecutar se obtiene:
$ testdbfile.pl abc => ABC ghi => GHI def => DEF