2012-03-05 12 views
5

Vorrei utilizzare un "regex compilato" (intendo: un'espressione nel formato qr/../) come chiave per una struttura hash.riconoscimento di "tipo" di chiavi hash

di discernere tra stringhe costanti e di queste espressioni regolari quando scorrere il Keyes hash, stavo cercando di usare ref(), o is_regexp(), ma gli ex restituisce una stringa nulla, e quest'ultimo non funziona. Temo che mi manchi qualcosa di fondamentale sui riferimenti Perl rispetto agli scalari.

A parte questo, la mia soluzione sembra funzionare. E 'troppo brutto comunque? Qualsiasi proposta alternativa è la benvenuta.

il codice per capire ref() funzione:

my $regex = qr/foo/; 
printf "ref(\$regex): %s \n", ref($regex); 
printf "is_regexp(\$regex): %d \n", is_regexp($regex); 
# ref($regex): Regexp 
# is_regexp($regex): 1 

my $scalar = 3; 
printf "ref(\$scalar): [%s] \n", ref($scalar); 
# ref($scalar): [] 

my %my_hash = ('name', 'Becky', 'age', 23); 
for my $k (keys %my_hash) { 
    printf "%s [%s] -> %s [%s] \n", $k, ref($k), $my_hash{$k}, ref($my_hash{$k}); 
} 
# name [] -> Becky [] 
# age [] -> 23 [] 
+5

Le chiavi in ​​un hash sono stringhe. 'ref' restituirà sempre' undef' per quelli. Se si utilizza qualcosa come una chiave che non è una stringa, viene convertita in stringa. – Qtax

risposta

7

Come Qtax fa notare nei commenti, Perl chiavi di hash sono sempre stringhe: se si usa qualcosa di diverso da una stringa come una chiave hash, è prima convertito a una stringa.

In un altro commento si scrive:

"Ho letto le definizioni contatore da un file di configurazione, voglio essere in grado di sostenere una sintassi modello, ad esempio: McDouglas, McDonald,/Mc [A-Za . -z] */ho poi letto i valori del contatore da file di testo, e aggiorno relativi contatori di conseguenza: McDonald 23 McIntosh 11"

Se ho capito questo diritto, una soluzione semplice potrebbe essere quella di memorizzare i espressioni regolari compilate in un altro hash, immesso nella stringa corrispondente:

my @patterns = (
    'McDouglas', 
    'McDonald', 
    'Mc[A-Za-z]*', 
); 

my %regexps = map +($_ => qr/^$_$/), @patterns; 
my %counters; 

while (<>) { 
    while (my ($pat, $re) = each %regexps) { 
     $counters{$pat}++ if /$re/; 
    } 
} 

foreach my $pat (@patterns) { 
    print "$pat: ", ($counters{$pat} || 0), "\n"; 
} 
2

qualcosa che non va con l'utilizzo di Tie::RegexpHash? Esso si evita di dover reinventare la ruota :)

use Tie::RegexpHash; 

my %hash; 

tie %hash, 'Tie::RegexpHash'; 

$hash{ qr/^5(\s+|-)?gal(\.|lons?)?/i } = '5-GAL'; 

$hash{'5 gal'};  # returns "5-GAL" 
$hash{'5GAL'};  # returns "5-GAL" 
$hash{'5 gallon'}; # also returns "5-GAL" 
+0

Mentre il pacchetto che suggerisci è piuttosto interessante, offre qualcosa di diverso da quello di cui ho bisogno. Nel mio caso, potrei anche memorizzare le semplici stringhe che definiscono le regex (ma vorrei perdere la pre-compilazione regex). Un caso in cui il trwo si avvicina allo scontro è quando è necessario memorizzare le espressioni rege parzialmente sovrapposte l'una all'altra. – AndreaG

+0

@AndreaG: fornire un esempio di cosa intendi. – Zaid

+0

Ho letto le definizioni del contatore da un file di configurazione; Voglio essere in grado di supportare alcuni sintassi di pattern, ad esempio: McDouglas, McDonald,/Mc [A-Za-z] * /. Poi leggo i valori dei contatori dai file di testo e aggiorno i contatori pertinenti di conseguenza: McDonald 23 McIntosh 11 – AndreaG

Problemi correlati