Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Constructing hashes

by Mark.Allan (Sexton)
on Jun 05, 2013 at 07:32 UTC ( [id://1037153]=perlquestion: print w/replies, xml ) Need Help??

Mark.Allan has asked for the wisdom of the Perl Monks concerning the following question:

hi Monks

I have a question regarding the use of hashes and whether this approach is feasible, I need to write a small piece of code which processes a list of servers, and for each server runs and command and pulls back what components are running against that server and pattern matches just the component name from the list

Example Server A Component1 Component2 Component3 Component4 Server B Component1 Component2 Component3 Server C Component1 Component2

And so on. The code I have is below

#!/usr/bin/perl $logfile="/tmp/gatherinfo.log"; @srvlist = ('serverA','serverB','serverC'); open(LOGFILE,">>$logfile")||die ("cannot create and open file"); foreach $_ (@srvlist){ chomp $_; @cmd = `pulldata -e $_`; foreach $line (@cmd) { chomp ($line); if ($line =~ '^\s+(\w+):\s.*') { $RM=$1; <ASSIGN TO HASH AND PRINT> print LOGFILE <hash content> } } } } close(LOGFILE);

I know hash uses key=value so what im looking to do is dynamically assign server stored in default variable $_ as key into the hash and the component value ($RM) as value and print it. Is this a pragmatic approach?

Replies are listed 'Best First'.
Re: Constructing hashes
by hdb (Monsignor) on Jun 05, 2013 at 07:51 UTC

    As long as there is only one component value ($RM) per server, this should be fine. If you use a hash %results, then you would say:

    $results{$_} = $RM; # or $1 to skip $RM alltogether print LOGFILE "$_: $RM\n"; # no need to retrieve from hash

    Your loop foreach $line (@cmd) implies there could be more than one. In which case a hash of arrays could be what you want:

    push @{ $results{$_} }, $RM;

    and the general remark that use strict; use warnings; is recommended for scripts.

    UPDATE: Re-read your question and have seen that there are several components indeed. So the second part of my answer applies. If you want to access your results, you would do this by $results{$server}->[$i] for the $i-th component.

Re: Constructing hashes
by rovf (Priest) on Jun 05, 2013 at 08:02 UTC
    Aside from a few harmless, but unlogical parts of your programs (for example, why do you chomp $_ when you already know that it can't end with a newline), I don't find that you clearly expressed your problem, so I have to guess a bit:

    The listing you write under "Example" is what should end up in the logfile, right? In this case, you just need to remember, whether you have already printed the server name for the logfile. Each server causes in several lines being printed (one line for each component), but only the first line will also contain the server name. I would therefore write your print statement in the following way:

    print "$server_name_or_blank $RM\n";
    and make sure that on the first iteration of the inner loop, $server_name_or_blank contains the name of the server, and on subsequent iterations of the inner loop it contains a string of spaces, of the same length the server name had been.

    A few additional remarks: First, always have "use strict; use warnings;" in your program. Second, I strongly advice against using $_ as a variable for the outer loop. There are many cases where Perl operations implicitly modify $_. Finally, don't modify the loop variable, unless you really know what you are doing; the loop variable is an alias to the respective list element, and by changing the variable, you also change the list element. Though this is harmless in your particular case, you will be bitten sooner or later, if you continue this practice.
    -- 
    Ronald Fischer <ynnor@mm.st>
Re: Constructing hashes
by hbm (Hermit) on Jun 05, 2013 at 11:35 UTC

    I second the suggestion - use $_ in your inner loop:

    for my $server (@servlist) { my @cmd = `pulldata -e $server`; for (@cmd) { ...

    Your regex is malformed - use //, or another delimiter like m##. And the trailing dot-star is wasteful.

    #if ($line =~ '^\s+(\w+):\s.*') if ($line =~ /^\s+(\w+):\s/)
Re: Constructing hashes
by rpnoble419 (Pilgrim) on Jun 05, 2013 at 14:13 UTC

    I would also store the server name and components in an external data source (database, YAML, etc). This way you can modify the server/component list without having to change your program. Small little utilities like this, tend to grow a life of their own, and a little forethought goes a long way to making you life easier..

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1037153]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (6)
As of 2024-04-18 06:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found