0

First off, let me tell you that I have worked very little with Arrays and never with Hashes. Also, Perl is not my strongest scripting language. I come from a background in shell scripting.

That said, I have this in a Perl script:

$monitored_paths = { '/svn/test-repo'  => 'http://....list.txt' };

The URL points to a file which contains a list of paths like this:

/src/cpp
/src/test
/src/test2

The objective is to replace the URL with the contents:

$monitored_paths = {'svn/test-repo' => '/src/cpp', '/src/test', '/src/test2'}

What would be the best way to achieve this? Thanks!

Sam

1
  • 1
    A hash it just an array indexed using a string instead of a number. Commented Jun 26, 2012 at 18:56

4 Answers 4

1

There is an error in the premise of your question, because this line:

$monitored_paths = {'svn/test-repo' => '/src/cpp', '/src/test', '/src/test2'}

is the equivalent of either of these:

$monitored_paths = {'svn/test-repo' => '/src/cpp', '/src/test' => '/src/test2'}
$monitored_paths = {'svn/test-repo', '/src/cpp', '/src/test', '/src/test2'}

What you really want is:

$monitored_paths = {'svn/test-repo' => ['/src/cpp', '/src/test', '/src/test2']}

where [] denotes an array reference. You create an array reference like this:

my $arrayref = [1, 2, 3]; # called an "anonymous array reference"

or like this:

my @array = (1, 2, 3);
my $arrayref = \@array; 

You want something such as:

$monitored_paths = { '/svn/test-repo'  => 'http://....list.txt' }
foreach my $key (keys %$monitored_paths) {
    next if ref $monitored_paths{$key} eq 'ARRAY'; # skip if done already
    my @paths = get_paths_from_url($key);
    $monitored_paths->{$key} = \@paths; # replace URL with arrayref of paths
}

replacing get_paths_from_url with your URL-fetching and parsing function (using LWP or whatever...since that was not really part of your question I assume you already know how to do that). If you write your function get_paths_from_url to return an array reference in the first place instead of an array, you can save a step and write $monitored_paths->{$key} = get_paths_from_url($key) instead.

Sign up to request clarification or add additional context in comments.

11 Comments

Excellent! Yes, I agree I did not present my question correctly. Sorry about that. Yes, I already figured out to LWP to fetch contents from the URL. I'll give your code a shot. Thanks!
No need to apologize, just describing the proper syntax. If it works, accept an answer please.
I'm afraid I'm unable to get it to work. The $monitored_paths is a mix of regular paths and URL's. So, running this over all the items using the foreach needs to be avoided. I need to put a "if ref..." after the foreach but can't quite get the syntax to check. Also, how can I print the contents of $monitored_paths in the end assuming everything went well? In the get_paths_from_url function, when I print content of $ARGV[0], I get /svn/test-repo a bunch of times on the screen. It should ideally be the URL. :(
Lots of questions... 1. I don't know what you want to do when it's not a URL then. Skip it with next if $monitored_paths{$key} =~m/^http/; 2. You can "print the contents" with use Data::Dumper; print Dumper($monitored_paths); 3. @ARGV is for command line arguments, subroutine arguments are passed into @_ (so first argument is $_[0], second is $_[1]). Hope it helps.
Yeah, I can use the match substring http I think. That should work. I'll give it a shot first thing tomorrow. If there is no http:, then we just skip it. I'll also try the Data::Dumper like you suggested. I tried using it in various other ways with no success. Thanks again! :)
|
0

If you want to read from the file and add each path to the array you could do something like:

use strictures 1;

my $monitored_paths = {};
open( my $FILE, '<', '/path/to/file' ) or die 'Unable to open file '. $!;
while($FILE){
    push @{ $monitored_paths->{'svn/test-repo'} }, $_;
}

3 Comments

Interesting. Actually, the monitored_paths, in addition to the URL has a bunch of other references as well. Can I just add your code to stack on top of it?
Sure. If you dump the monitored_paths variables you'll see the 'svn/test-repo' and the routes. If you need more keys just push them on to different keys depending on a condition. print Dumper($monitored_paths);
That won't work because they value of $monitored_paths->{'svn/test-repo'} is not an array reference yet, you cannot push on it. You can add a check using ref() before the push, and set it to [] if ref() is false.
0
use LWP::Simple;
my $content = get($url); ## do some error checking
$monitored_paths = {'svn/test-repo' => [split( "\n", $content)]}

2 Comments

No, this is not possible. I cannot hard-code the paths. They have to reside in the URL and have to be read during runtime.
Lookup URL using the original hash and perform a get on those URLs and create a new hash.
0
use LWP;
foreach (keys %monitored_paths)
{
   my  $content = get($monitored_paths{$_});# Perform error checking
   $monitored_paths_final {$_} = join(",",split("\n",$content));
}

1 Comment

There is a bug in that code, it creates a new hashref and assigns it to $monitored_paths_final each time. You will end up with only one key in it (the last one in the loop).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.