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

Hi,

I have been trying to think up a way to access a hash from an external file. I want to be able to read the values and print it out from the external file.

What I mean is if I have a perl file with:

File_a.pl:

my %test_hash = ( a=>1, b=>2);

Then from File_b.pl (the external file) I want to be able to print the values of inside %test_hash.

File_b.pl:

foreach (keys %test_hash){

print "$test_hash{$_}\n";

}

How do I do this without modifying File_a.pl?

EDIT: Updated to fix a typo with the declaration of the hash. Also, there are other variables(including other hashes) defined in File_a.pl

  • Comment on Trying to access hash from external perl file

Replies are listed 'Best First'.
Re: Trying to access hash from external perl file
by toolic (Bishop) on Jul 11, 2012 at 16:42 UTC
    How do I do this without modifying File_a.pl?
    I think you do want to modify File_a.pl to use parens instead of curlies List value constructors:
    %test_hash = (a=>1, b=>2);

    Then you can require in File_b.pl:

    require 'a.pl'; foreach (keys %test_hash){ print "$test_hash{$_}\n"; }
Re: Trying to access hash from external perl file
by davido (Cardinal) on Jul 11, 2012 at 17:55 UTC

    You've already got the right answer(s) for how to pull the hash into your script. But after a recent Perl Mongers meeting, I thought it worth mentioning the following:

    If you're using that hash to handle configuration information, you may find it useful (and more powerful) to use tilly's new Template::ExpandHash module. This will not be a drop-in solution for your existing strategy, but rather, a new way of looking at using hashes for configuration data. It's a well thought out module. His presentation to LAPM was really interesting. The slide presentation can be found here: http://elem.com/~btilly/template-hashexpand/#title-slide.


    Dave

Re: Trying to access hash from external perl file
by tobyink (Canon) on Jul 11, 2012 at 16:44 UTC

    Firstly I'm assuming your example File_a.pl hash contains a typo, and the real file uses rounded parentheses, not curly braces (curly braces are for hashrefs).

    Now, if your File_a.pl really does just consist of a single hash definition and no other code, then it's quite simple...

    my %test_hash = do 'File_a.pl'; foreach (keys %test_hash) { print "$test_hash{$_}\n"; }

    If there's other stuff in File_a.pl, then it becomes a bit harder. You'd need to slurp the contents of File_a.pl into a variable, strip that other stuff out of the variable, probably using regular expressions, then eval it.

    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
Re: Trying to access hash from external perl file
by daxim (Curate) on Jul 11, 2012 at 16:43 UTC
    The hash assignment is wrong. It must use parentheses, not braces: %test_hash = (a=>1, b=>2);

    In File_b.pl, load the file with do:

    my %test_hash = do 'File_a.pl'
Re: Trying to access hash from external perl file
by kennethk (Abbot) on Jul 11, 2012 at 16:48 UTC

    Well, there are a couple methods, but none is particularly clean from my perspective. The right™ way to do this is to edit File_a.pl to be a module (perlmod), and interact with it programmatically. However, given your spec, I can see two ways to proceed.

    1. If the assignment to %test_hash occurs in the main package and the hash is not lexical (declared with my, see Private Variables via my()), you can use the do mechanism to literally execute the file. Obviously, this will also invoke all the many side effects of the script, which may be undesirable.
    2. You could open the file, strip out the relevant declaration, perhaps using a regex, and then feed it into an eval.

    Both of these feel fragile to me, but they will do the job.


    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Re: Trying to access hash from external perl file
by ruhroh (Initiate) on Jul 11, 2012 at 17:13 UTC

    Ok thanks for all the replies. Yes, there is a typo in my code. Sorry about that, it has been corrected.

    Also, there isn't a package keyword used File_a.pl so it isn't in any specified namespace. The hash does have a lexical scope. I edited the code to reflect that as well.

    To clarify further, I can't modify File_a.pl

    I tried the "do" keyword and couldn't access the data. Perhaps I'll try the slurp keyword.

      Well, seeing as you fail the conditions on option 1 I gave in Re: Trying to access hash from external perl file, that leaves a regular expression/eval combo after slurping the file. For the line you've posted above, you could use /(\Qmy %test_hash = (\E.*)/ to grab the necessary information. However, this would break if for example, the hash definition was on multiple lines or whitespace differed in any way from what you posted. All of these can be overcome with changes to the regex, but you need to know the specific use case, and presumably how this script might change in the future. And this whole approach presumes that the hash is defined completely in the statement in which it's declared.


      #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Re: Trying to access hash from external perl file
by Anonymous Monk on Jul 11, 2012 at 21:23 UTC