2008-11-21 19 views
7

Estoy escribiendo un script que probablemente será modificado por los usuarios. Actualmente estoy almacenando las configuraciones dentro del script. Existe en forma de hash-of-hashes.¿Cómo puedo cambiar la caja de una clave hash?

Me gustaría protegerme de que las personas accidentalmente usen caracteres en minúscula en las teclas hash, porque eso romperá mi script.

Sería fácil inspeccionar las teclas hash y simplemente emitir advertencias para las teclas con caracteres en minúscula, pero prefiero corregir la distinción entre mayúsculas y minúsculas automáticamente.

En otras palabras, quiero convertir todas las claves hash en el hash de nivel superior en mayúsculas.

Respuesta

13

de Andy es una buena respuesta, salvo que uc s cada llave, y luego uc es nuevo si no coincide.

Este uc s una vez:

%hash = map { uc $_ => $hash{$_} } keys %hash; 

Pero ya que usted ha hablado de los usuarios que almacenan claves , un empate es una forma mucho más segura, aunque más lento.

package UCaseHash; 
require Tie::Hash; 

our @ISA = qw<Tie::StdHash>; 

sub FETCH { 
    my ($self, $key) = @_; 
    return $self->{ uc $key }; 
} 

sub STORE { 
    my ($self, $key, $value) = @_; 
    $self->{ uc $key } = $value; 
} 

1; 

Y entonces en el principal:

tie my %hash, 'UCaseHash'; 

Eso es un espectáculo. El tie "magia" lo encapsula, por lo que los usuarios no pueden, sin saberlo, meterse con él.

Por supuesto, siempre y cuando se está utilizando una "clase", se puede pasar el nombre de archivo de configuración e iniciar desde allí:

package UCaseHash; 
use Tie::Hash; 
use Carp qw<croak>; 

... 

sub TIEHASH { 
    my ($class_name, $config_file_path) = @_; 
    my $self = $class_name->SUPER::TIEHASH; 
    open my $fh, '<', $config_file_path 
     or croak "Could not open config file $config_file_path!" 
     ; 
    my %phash = _process_config_lines(<$fh>); 
    close $fh; 
    $self->STORE($_, $phash{$_}) foreach keys %phash; 
    return $self; 
} 

Donde tendría que llamar así:

tie my %hash, 'UCaseHash', CONFIG_FILE_PATH; 

... asumiendo algunas constantes CONFIG_FILE_PATH.

+1

Usted sabe, hay un módulo en CPAN que hace esto. No necesita codificarlo usted mismo: Hash :: Case, consulte http://search.cpan.org/dist/Hash-Case/ – bart

+0

Su método sobrescribirá todo el hash, mientras que el método de Andy solo sobrescribirá los minúsculos. A menos que espere que el hash contenga una gran cantidad de claves en minúsculas (lo que no es probable en este escenario), no será más rápido. –

+1

Gracias por el aviso, Bart. Olvidé la primera regla de Perl Club: no hables antes de haber revisado CPAN. Mi publicación comenzó una simple ilustración de una clase empatada, y luego me volví elegante. Doh! – Axeman

13

Recorre el hash y reemplaza las teclas en minúsculas con sus equivalentes en mayúsculas y elimina las antiguas. Aproximadamente: Respuesta

for my $key (grep { uc($_) ne $_ } keys %hash) { 
    my $newkey = uc $key; 
    $hash{$newkey} = delete $hash{$key}; 
} 
0

Esto convertirá hash de varios niveles a minúsculas

my $lowercaseghash = convertmaptolowercase(\%hash); 

sub convertmaptolowercase(){ 
    my $output=$_[0]; 
    while(my($key,$value) = each(%$output)){ 
     my $ref; 
     if(ref($value) eq "HASH"){ 
      $ref=convertmaptolowercase($value); 
     } else { 
      $ref=$value; 
     } 
     delete $output->{$key}; #Removing the existing key 
     $key = lc $key; 
     $output->{$key}=$ref; #Adding new key 
    } 
    return $output; 
} 
Cuestiones relacionadas