tags:

views:

167

answers:

5

I have a hash in Perl which has been dumped into from some legacy code the name of the key has now changed from simply reqHdrs to reqHdrs.bla

$rec->{reqHdrs.bla}

My problem is now I cant seem to access this field from the hash any ideas? The following is my error

Download Script Output: Bareword "reqHdrs" not allowed while "strict subs" in use
+4  A: 

If the key is a string, just:

$rec->{"reqHdrs.bla"}
Eli Bendersky
...with a very tiny performance gain if you use a single-quoted ( `'` ) rather than a double quoted ( `"` ) string ;)
Carl Smotricz
@Carl: why is a single quote faster?
Eli Bendersky
@Eli: Single quotes don't interpolate.
Michael Carman
@Michael, yes but can't that be easily optimized away by Perl for strings w/o interpolation variables?
Eli Bendersky
The double quote allows you (always, not just in `print` statements) to use interpolated variables, e.g. `"foo$number"`. It's my understanding that a double-quoted string will force Perl to make a quick check for a variable buried in the string before going ahead and doing what it would have done with a plain single-quoted string.
Carl Smotricz
That's also why I said "tiny." In a good Perl implementation, the extra effort may be only in the compilation phase, which however is usually done once at the beginning of every execution.
Carl Smotricz
@Eli: Judging by the output of `perl -MO=Terse`, it can. There's a school of thought that says you should use single-quotes where you can to provide a hint *to the programmer* that interpolation isn't necessary, though that can bite you if you ever add something requiring interpolation and forget to change the quotes.
Michael Carman
@Carl: There is only one implementation of Perl. Perl 6 will have a formal specification, allowing multiple implementations. (e.g. Pugs and Rakudo)
Michael Carman
A: 

The bareword reqHdrs.bla is really just a... synonym, I guess, for a string. I'm not completely sure, but I think you should be able to simply use a string, e.g. 'reqHdrs.bla' as your key and that should retrieve your value OK.

Carl Smotricz
+2  A: 

Enclose the key in quotes:

$rec->{'reqHdrs.bla'}
codaddict
+12  A: 

As described in perldoc perldata:

...An identifier within such curlies is forced to be a string, as is any simple identifier within a hash subscript. Neither need quoting. Our earlier example, $days{'Feb'} can be written as $days{Feb} and the quotes will be assumed automatically. But anything more complicated in the subscript will be interpreted as an expression. This means for example that $version{2.0}++ is equivalent to $version{2}++, not to $version{'2.0'}++.

In general, if you have a hash key with a character outside the [A-Za-z0-9_] range, use quotes (either single or double) inside the braces. As with normal strings, contents in double quotes will be parsed for any contained variables, while single quoted strings are taken literally:

use strict; use warnings;
use Data::Dumper;
my $x = 1;
my %hash = (
    bare_string => 'hi there',
    "not a bare string" => 'yup',
);
$hash{'$x'} = 'foo';
$hash{"$x"} = 'bar';
print Dumper(\%hash);

prints:

$VAR1 = {
      'bare_string' => 'hi there',
      'not a bare string' => 'yup',
      '$x' => 'foo'
      '1' => 'bar',
    };
Ether
Upvote for the most comprehensive and helpful answer of the lot. :)
Carl Smotricz
+3  A: 

According to perldoc perldata that when an identifier is used within curlies, such as when accessing a hash value via a key, that identifier is assumed to be a string and is treated as such. Quotes will be assumed automatically, however, anything more complicated can be interpreted.

From perldata

In fact, an identifier within such curlies is forced to be a string, as is any simple identifier within a hash subscript. Neither need quoting. Our earlier example, $days{'Feb'} can be written as $days{Feb} and the quotes will be assumed automatically. But anything more complicated in the subscript will be interpreted as an expression. This means for example that $version{2.0}++ is equivalent to $version{2}++ , not to $version{'2.0'}++ .

Since the . is used for string concatenation, the interpreter I'm guessing is trying to concat those two strings together. Regardless it's always better to just use quotes to make it explicit, and if you have strict on it will probably throw a "bareword not allowed" error.

The solution to your problem:

$rec->{'reqHdrs.bla'}
Logan
I did not see the previous post that quoted the same snippet from perldata.
Logan