2008-11-21 6 views
7

Ich schreibe ein Skript, das wahrscheinlich von Benutzern geändert wird. Momentan speichere ich die Konfigurationseinstellungen im Skript. Es existiert in Form eines Hash-of-Hashes.Wie kann ich den Fall eines Hash-Schlüssels ändern?

Ich möchte mich vor Leuten schützen, die versehentlich Kleinbuchstaben in den Hash-Schlüsseln verwenden, weil das mein Skript brechen wird.

Es wäre einfach, die Hash-Schlüssel zu überprüfen und nur Warnungen für alle Schlüssel mit Kleinbuchstaben auszustellen, aber ich würde lieber die Groß-/Kleinschreibung automatisch beheben.

Mit anderen Worten, ich möchte alle Hash-Schlüssel im Top-Level-Hash in Großbuchstaben konvertieren.

Antwort

13

Andy Antwort ist eine gute Antwort, außer er uc s jeden Schlüssel, und dann uc es wieder s, wenn sie nicht übereinstimmt.

Diese uc s es einmal:

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

Aber da Sie von Benutzern Speicherung Schlüssel sprach, ist ein Unentschieden ein viel sicherer Weg, auch wenn langsamer.

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; 

Und dann in Haupt:

tie my %hash, 'UCaseHash'; 

dass eine Show ist. Die tie "Magie" kapselt es, so dass die Benutzer nicht unwissentlich damit umgehen können.

Natürlich, solange Sie eine „Klasse“ verwenden, können Sie in der Konfigurationsdatei Namen übergeben und initialisieren es von dort:

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

Wo es Ihnen gefällt nennen müsste:

tie my %hash, 'UCaseHash', CONFIG_FILE_PATH; 

... unter der Annahme einiger Konstante CONFIG_FILE_PATH.

+1

Sie wissen, in Kleinbuchstaben, gibt es ein Modul auf CPAN, die dies tut. Keine Notwendigkeit, es selbst zu codieren: Hash :: Case, siehe http://search.cpan.org/dist/Hash-Case/ – bart

+0

Ihre Methode wird den gesamten Hash überschreiben, während Andy's Methode nur Kleinbuchstaben überschreiben wird. Sofern Sie nicht erwarten, dass der Hash eine große Menge an Kleinbuchstaben enthält (in diesem Szenario nicht wahrscheinlich), wird er nicht schneller sein. –

+1

Danke für die Köpfe hoch, Bart. Ich habe die erste Regel von Perl Club vergessen: Sprechen Sie nicht, bevor Sie CPAN überprüft haben. Mein Beitrag begann mit der einfachen Illustration einer gebundenen Klasse, und dann wurde ich schick. Do! – Axeman

13

Gehen Sie durch den Hash und ersetzen Sie alle Kleinbuchstaben mit ihren Großbuchstaben Äquivalenten, und löschen Sie die alten. Grob:

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

Diese Multi-Level-Hash konvertieren

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