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

I've got a program that I've inherited which stores its data in hashes like this:
${input_queue}{"name"} = "blah";
My problem is that I have trouble printing such things. I have attempted something like:
print "name is ${input_queue}{"name"}\n";
but it seems to choke on the first quote arount "name". My hash knowledge is pretty limited, but I'm reasonably sure that there'd be more than one way to print this baby. Any suggestions?

Replies are listed 'Best First'.
(tye)Re: Hash Printing Question
by tye (Sage) on Dec 01, 2000 at 01:43 UTC

    ${hash}{"key"} is the same as $hash{"key"} (for reasonably named variables) so I'd suggest you adopt the second style for most uses. But in a string expansion, ${var} is used like $var but (at least usually) stops interpretting at the closing } (this is all a bit imprecise in an attempt to be DWIMish) so you can write "Sold $n ${item}s" instead of "Sold $n $item"."s". So "${hash}{'key'}" is the same as $hash."{'key'}".

    And $hash{"key"} is the same as $hash{key} if "key" is just letters, numbers, and underscores. So you can use any of these:

    print "name is $input_queue{name}\n"; print "name is $input_queue{'name'}\n"; print qq<name is $input_queue{"name"}\n>; print "name is ".$input_queue{"name"}."\n";
    to name just a few.

            - tye (but my friends call me "Tye")

      One minor correction:

      And $hash{"key"} is the same as $hash{key} if "key" is just letters, numbers, and underscores.

      I was worried that I didn't get that quite right and for good reason, too. $hash{"012"} is different than $hash{012} which is actually the same as $hash{"10"} since 012 (octal) == 10 (decimal). I worry there may be other special cases as well.

      Also, on slightly old versions of Perl, things like $hash{time} will get you a warning because, on even older versions of Perl, that meant $hash{time()} and we needed a transition period before it could unambiguously mean $hash{"time"} like it does now.

              - tye (but my friends call me "Tye")
Re: Hash Printing Question
by chipmunk (Parson) on Dec 01, 2000 at 01:35 UTC
    Perl chokes on that line because you're trying to use double-quotes inside a double-quoted string. To Perl, this is one string: "name is ${input_queue}{" and this is another string: "}\n".

    Here are several different ways to do what you're trying to do:

    1. Use single quotes on the hash key.
      print "name is ${input_queue}{'name'}\n";
    2. Don't use any quotes on the hash key.
      print "name is ${input_queue}{name}\n";
      This works because the key, 'name', is a bareword. It wouldn't work with a key like 'this-is-a-key'.

    3. Use a quoting operator on the string.
      print qq(name is ${input_queue}{"name"}\n);
      qq{} is just like double-quotes, but you get to choose the delimiter.

    One last point: the braces around the hash name are optional: $input_queue{name} = "blah";. If you prefer the extra braces, that's okay too.

    UPDATE: Please see tye's answer for why ${input_queue}{'name'} doesn't mean the same as $input_queue{'name'} in a double-quoted string.

      As a matter of habit I prefer to use single quotes when (I need quotes) just to emphasize that no interpolation is expected (though that should be kind of obvious in this case ;-). For me I think it makes reading the code later a bit easier than defaulting to double quotes everywhere.
Re: Hash Printing Question
by boo_radley (Parson) on Dec 01, 2000 at 01:33 UTC
    something like
    print "name is ", $hash{$foo}{"name"}, "\n";
    or
    my $thisname = $hash{$foo}{"name"}; print "name is $thisname\n";
    works for me.
      Thanks, folks. My programming habits had painted me into a corner.
      I had hoped that there would be an embarrassingly simple answer, and there was!
      Sankya, sankya, sankya.
Re: Hash Printing Question
by KM (Priest) on Dec 01, 2000 at 01:30 UTC
    Try:

    print qq{name is $input_queue{"name"}}; # or print qq{name is } . ${input_queue}{"name"};

    Cheers,
    KM

Re: Hash Printing Question
by 2501 (Pilgrim) on Dec 01, 2000 at 01:31 UTC
    I don't see the point of ${input_queue} but in general, for a hash all keys are considered strings so you don't even need the double quotes.
Re: Hash Printing Question
by arturo (Vicar) on Dec 01, 2000 at 01:35 UTC

    2501 is right, hash keys are not considered to be barewords under -w and use strict, but you can also single quote it.

    print "name: ${input_queue}{'name'}\n";

    Philosophy can be made out of anything. Or less -- Jerry A. Fodor

      When I did that, I got the following:
      name: {'name'}
      as output.
        Oops... In a double-quoted string, ${input_queue}{'name'} is interpreted as the scalar variable $input_queue, followed by the string {'name'}. I didn't realize that when I wrote my answer either.

        So, you really do need to remove those extra braces: print "name: $input_queue{'name'}\n";