neshura has asked for the wisdom of the Perl Monks concerning the following question:

Is it possible to do something clever with regexes within a hash key? E.g., in the following code, it's not possible to access $1, $2, ... from within the curly braces (or the regular braces for an array, though the list of matches returned in a regex is not as potentially useful in an array). The following code isn't obfuscated, but it shows what I would like to be able to do.
$nerf{"my"} = "fridge"; $nerf{"0"} = "truth"; $nerf{"1"} = "beauty"; @nerf = ('i', 'love', 'cheese'); $_ = 'my funny valentine'; print "print ctxt 1: ", /^(\w*)/, " $&", "\n"; # good - this regex returns the # match b/c it's a list context print "print ctxt 2: ", /^\w*/, " $&", "\n"; # good - this regex returns a # 1 b/c there are no parentheses $x = $nerf{/^(\w*)/}; print "hash ctxt: ", $x, " $&", "\n"; # this regex returns a 1 despite the # parentheses because it wants a scalar # but dammit, i'd like to be able to do regexes # within hash keys $y = $nerf[/^(\w*)/]; print "array ctxt: ", $y, " $&", "\n" # this regex also returns a 1 despite the parentheses
According to the Sacred Book (p. 209), "One never needs to force evaluation in a list context, because any operation that wants a list already provides a list context to its list arguments for free." But what if one is particularly ornery? Does anyone know a 1-line hack to get around this particular hashkey-regex instance?

Replies are listed 'Best First'.
Re: Contexts for regex evaluations
by Anonymous Monk on Feb 10, 2000 at 17:11 UTC

    I dont understand exaclty what are you trying to do...

    If you want to do a regex over the keys of a hash and
    get some part of them using backreferences, then
    something like

    @p=map /(\w+)/g, keys %nerf;
    

    would work; it takes all keys, get all secuences of
    word chars from each key and return the array with all
    the parts. Or, for instance, if you want only the values
    whose keys match some regex, you could do
    @v=map $nerf{$_}, map /^(\d+)$/, keys %nerf;
    

    (this gets all values from %nerf where the key is a number)
    Or even, get a new hash with the subset of the previous
    hash pairs where the key matches the regex:
    %sh=map {($_=>$nerf{$_})} map /^(\d+)$/, keys %nerf;
    

    Now, if what you want is to apply a regex to $_ or other
    string, take all the backreferences for it, and then
    get the values from the hash whose key its one of those
    backreferences, something like
    @v=map exists $nerf{$_} ? $nerf{$_} : (), /(\w+)/g;
    %sh=map exists $nerf{$_} ? ($_=>$nerf{$_}): (), /(\w+)/g;
    

    (in this case, that gets all words from $_ and gives you
    the array of values of the subset of the hash)

    Now this is obfuscated, right? :-)

RE: Contexts for regex evaluations
by mikfire (Deacon) on Feb 10, 2000 at 19:52 UTC
    $x = $nerf{(/^(\w*)/)[0]}; print "hash ctxt: ", $x, " $&", "\n";
    Mik Firestone
      thanks -- that's exactly what i was looking for