2008-11-21 5 views
7

J'écris un script susceptible d'être modifié par les utilisateurs. Actuellement, je stocke les paramètres de configuration dans le script. Il existe sous la forme d'un hachage de hash.Comment puis-je changer le cas d'une clé de hachage?

Je voudrais éviter que des personnes n'utilisent accidentellement des caractères minuscules dans les clés de hachage, car cela casserait mon script.

Il serait simple d'inspecter les clés de hachage et d'émettre simplement des avertissements pour toutes les clés avec des caractères minuscules, mais je préférerais régler la sensibilité à la casse automatiquement. En d'autres termes, je souhaite convertir toutes les clés de hachage du hachage de premier niveau en majuscules.

Répondre

13

Andy est une bonne réponse, sauf qu'il uc de toutes les clés, puis uc est encore si elle ne correspond pas.

Ce uc s une fois:

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

Mais depuis que vous avez parlé des utilisateurs clés stockage, une cravate est une manière beaucoup plus sûre, même si plus lent.

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; 

Et puis dans le principal:

tie my %hash, 'UCaseHash'; 

C'est un spectacle. La "magie" tie l'encapsule, de sorte que les utilisateurs ne peuvent pas, sans le savoir, jouer avec.

Bien sûr, aussi longtemps que vous utilisez une « classe », vous pouvez passer dans le nom du fichier de configuration et l'initialiser à partir de là:

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; 
} 

Où vous devez l'appeler comme:

tie my %hash, 'UCaseHash', CONFIG_FILE_PATH; 

... en supposant une constante CONFIG_FILE_PATH.

+1

Vous savez, il y a un module sur CPAN qui fait cela. Pas besoin de coder vous-même: Hash :: Case, voir http://search.cpan.org/dist/Hash-Case/ – bart

+0

Votre méthode remplacera l'ensemble de hachage, alors que la méthode de Andy n'écrasent les en minuscules. À moins que vous ne vous attendiez à ce que le hachage contienne un nombre impressionnant de minuscules (ce qui n'est probablement pas le cas dans ce scénario), il ne sera pas plus rapide. –

+1

Merci pour les heads up, bart. J'ai oublié la première règle de Perl Club: Ne parlez pas avant d'avoir vérifié CPAN. Mon article commençait par une simple illustration d'une classe liée, et ensuite j'ai eu envie. Doh! – Axeman

13

Parcourez le hachage et remplacez les majuscules minuscules par leurs équivalents majuscules, et supprimez les anciennes. En gros: la réponse de

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

Cela va convertir hachage à plusieurs niveaux en minuscules

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; 
} 
Questions connexes