Re: sorting a hash that's in another file
by dbwiz (Curate) on Jul 23, 2003 at 21:01 UTC
|
Assuming that you know the hash name, and that it is a real hash, not a reference, this one would work.
Caveat! Your example has one key named "color" and the other named "colors". You should unify them.
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my $other = 'somescript.pl';
my $find = '%some_hash';
open SCRIPT, "< $other"
or die "can't open\n";
my $first = "";
my $hash_text = "";
while (<SCRIPT>) {
if (!$first) {
$first = /$find/;
}
next unless $first;
s/^\s*my $find/$find/;
$hash_text .= $_;
last if /\)/;
}
close SCRIPT;
my %some_hash; # must be the same name as the hash in the other scrip
+t
eval $hash_text;
my %colors ;
for ( keys %some_hash) {
for my $color ( split /,\s?/, $some_hash{$_}{colors}) {
push @{$colors{$color}}, $_;
}
}
print Data::Dumper->Dump([\%colors], ['colors']),$/;
__END__
$colors = {
'blue' => [
'MASSACHUSETTS',
'NEW_YORK'
],
'green' => [
'NEW_YORK'
],
'black' => [
'NEW_YORK'
],
'white' => [
'MASSACHUSETTS'
],
'red' => [
'MASSACHUSETTS'
]
};
Notice that this code will break if your hash contains a literal ")". But just to give you the idea.
| [reply] [d/l] |
Re: sorting a hash that's in another file
by BrowserUk (Patriarch) on Jul 23, 2003 at 21:05 UTC
|
Assuming that the reason you don't want to execute the script is because the script contains other stuff besides the hash, then something like this might work. The regex is far from foolproof, but short of writing a Parse:RecDescent grammer to match perl, which is a very tall order, you might get away with the following (with a little tweaking as necessary).
It requires that none of the keys or values in the hash is likely to contain the sequence ');' and that the hash declaration is finished with that sequence. If that isn't true, then move on to the next idea:)
Output
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
| [reply] [d/l] [select] |
|
|
First off, I'd like to say thanks to everyone who has contributed to this thread. You've all helped me immensely--either by code examples or by giving me perspective on my problem.
I think I've run into a problem that may require me to rethink the process by which I grab these values. It turns out that some of the hashes in %some_hash have different numbers of elements. So it looks something like:
%some_hash =
(
'NEW_YORK' =>
{ 'capital' => 'Albany',
'colors' => 'red, white, blue',
'bird' => 'pigeon'
},
'MASSACHUSETTS' =>
{ 'capital' => 'Springfield',
'colors' => 'green, yellow',
}
# etc
);
This is forcing me to rethink the entire process, and will probably mean that we break %some_hash out into its own file (as some of you suggested). Also my colleague just told me that the utility of what I'm doing (this is a pet project) is somewhat limited for other reasons related to the function of the original script.
But that doesn't temper my gratitude for the attention I've recieved. Thank you Monks. I learned a lot here.
AH
| [reply] [d/l] |
Re: sorting a hash that's in another file
by Abigail-II (Bishop) on Jul 23, 2003 at 20:49 UTC
|
You probably want any of use, require
or do.
Abigail | [reply] |
|
|
Abigail,
That was my initial thought, but the problem that I'm running into is that (and I may be wrong here) those operators actually execute the specified file, and the file is a CGI script that expects various inputs--without which it won't run. Or rather, I don't know exactly what the effect would be (it's a 3500+ line module).
Really what I need is some way to get the variables that are declared and use those in my script. Looking at the Camel, it doesn't seem like do, use, require do that sort of thing.
Are my assumptions about those functions correct?
AH
| [reply] [d/l] |
|
|
If you want to "grab" a variable out of a program, you have
two options: run the code, or parse the code. If you don't
want to run it (and you don't), you'd have to parse Perl,
unless you can assume something about your variable to make
it easier to grab.
Abigail
| [reply] |
Re: sorting a hash that's in another file
by tedrek (Pilgrim) on Jul 23, 2003 at 21:38 UTC
|
Is there some reason you can't just copy the hash into your script manually, it appears to be the sort of data that is relatively static. Alternatively if you have access to the module that declares the hash is there some reason that you can't rewrite it to get that hash from a third module? eg. in both scripts:
use States;
my %some_hash = %States::some_hash;
| [reply] [d/l] |
|
|
Tedrek,
There is a reason: the file is frequently updated by other developers. Those developers are only concerned with adding items to each of the hashes within %some_hash. In other words, they are concerned with adding more birds to MASSACHUSETTS (quite a bunch of pro-environment developers here ;-) ). However, it is useful (IMHO) for us to be able to see which birds are associated with which states (names of keys/values have been changed to protect the innocent--the "birds" are actually user IDs and the "states" are various functions... long story).
However, your idea to put the values in a separate module is excellent, and I will likely do just that (see my above reply).
Cheers,
AH
| [reply] |
Re: sorting a hash that's in another file
by snax (Hermit) on Jul 23, 2003 at 20:42 UTC
|
Well, if you're confident that you can read in just the hash definition -- say into an array -- and that you're sure that there's no way that this would end up being tainted maliciously, you can use join to get it all into one string and then eval to execute it. | [reply] |
|
|
Hmm. I was a lot more confident until all those bold tags started showing up ;).
Seriously, I'm working on my pattern match now, and it's non-trivial (at least for me), so if anyone has an alternative to doing something like:
open SCRIPT, "script.pl" or die "you scurvy dog";
while (<SCRIPT>) {
if ( grep(/\[... insert insane pattern match here ...]%some_hash[...
+ and here ...]/, $_) ) {
I'm eager to hear. I wish that I could just require the script w the hash in it, but that will not work right.
AH
| [reply] [d/l] |
|
|
Well, off the top of my head, I think this
would work:
open SCRIPT, "script.pl" or die "you scurvy dog";
while (<SCRIPT>) {
# Find the declaration
next unless /\%some_hash/;
$hash_declaration = $_;
# Now pop out and do another while loop
last;
}
while (<SCRIPT>) {
# Keep appending until we reach a semi-colon
$hash_declaration .= $_;
last if /;/;
}
eval($hash_declaration);
But this assumes that you won't have a semi colon in
the hash declaration in script.pl.
There's a zillion ways to do the reading-in part, too,
beyond just a smarter test for when you're done.
| [reply] [d/l] |
|
|
Re: sorting a hash that's in another file
by NetWallah (Canon) on Jul 31, 2003 at 17:07 UTC
|
Hi alienhuman - I just saw your message saying that you ARE dealing with a package.
Well - that should make life a lot easier - in your code, you simply use the package, and import the hash you need. If it is not explicitly exported, I believe you can still get at it using syntax like:
use ExistingPackage;
my %copy_of_Hash = ExistingPackage::%some_hash;
I'm a fairly new monk myself, so I'm not that sure of the syntax. | [reply] [d/l] |
|
|
my %copy_of_Hash = %ExistingPackage::some_hash;
Though you have to be sure that the %ExistingPackage::some_hash variable is not declared with the "my" operator in the module, or it's not accessible--even if it's in the main subroutine (as I found to my dismay and confusion).
Cheers,
AH
| [reply] [d/l] [select] |
| A reply falls below the community's threshold of quality. You may see it by logging in. |