in reply to Re: pulling more data from an array
in thread pulling more data from an array

First off, sorry if I offended anyone, that was not what I was trying to do. Just rushing to get this working and not getting very far, sorry about that. I do have some questions about your code, you've gotten rid of the parts that I need to produce the data. Was this to show how to handle the data once I get it? I know I'll have some questions on how you get Result 1 and Result 2, but wanted to apologize first and check on the code that gets me the data. Let me play around with this and better compose some questions. I'll also come up with some useful examples. Thanks for your comments and code. -Chris

Replies are listed 'Best First'.
Re^3: pulling more data from an array
by kennethk (Abbot) on Aug 05, 2010 at 14:36 UTC
    Like I said, "I assume that this is unintentional". A large fraction of the traffic through SoPW is asking monks to do people's work for them pro bono. If you want to learn Perl, this site has a large number of very smart, very talented programmers who are willing to give you a lot of patient assistance. In my short tenure, I know I've gotten a lot of very good advice and a lot of patient hand-holding from better men than me.

    you've gotten rid of the parts that I need to produce the data. Was this to show how to handle the data once I get it?

    I did that because I don't have all those modules installed, so I couldn't execute your script as posted. However, as you posted the result of Data::Dumper, I used that to replicate your internal state as the crux of your question was how to manipulate the data. I try and do my best to test code before I post, since posting broken code yields more confusion than assistance. I would expect the following (obviously untested) code to replicate my output with your data collection technique:

    #!/usr/bin/perl use lib qw(blib lib); use strict; use warnings; use Getopt::Long; use Pod::Usage; use Data::Dumper; use Opsware::NAS::Client; use Net::Ping; use POSIX qw(strftime); #use TrueControlAPI; my($user,$pass,$host) = ('na_admin', 'na4adm1n', 'localhost'); my $help = 0; my $nas = Opsware::NAS::Client->new(); my $res = $nas->login(-user => $user, -pass => $pass, -host => $host, +-nosession => '0'); print " \n"; #$res = $nas->show_configlet(host => "dev1", start => "snmp-server hos +t", end => "!"); $res = $nas->show_configlet(host => "dev2", start => "snmp-server host +", end => "!"); #$res = $nas->show_deviceinfo(ip => '10.253.74.70'); unless ($res->ok()) { printf STDERR ("*** error: %s\n", $res->error_message()); exit(1); } print (Dumper([$res->result()]), "\n\n"); my $result_1; for (split /(?<=\n)/, $res->result()) { next unless /^\Qsnmp-server host\E/; $result_1 .= $_; } print "---Result 1---\n$result_1\n\n"; my $result_2; for (split /(?<=\n)/, $res->result()) { next unless /^\Qsnmp-server\E/; s/^((?:\S+\s+){3})\S+/${1}Bob/; $result_2 .= $_; } print "---Result 2---\n$result_2\n\n";

    Regarding my algorithm for obtaining the first result, it can be broken down as follows:

    1. split the data string at any location preceded by ((?<=...)) a new line character (\n)
    2. Iterate over the resulting list in a foreach loop (Foreach Loops). As there is no explicit loop variable provided, $_ is used by default. Note that for and foreach are literal synonyms.
    3. Test the regular expression ^\Qsnmp-server host\E. As there is no explicitly bound variable (Binding Operators), $_ is used. ^ requires that the match start at the beginning of the string. The escapes \Q and \E (Quote and Quote like Operators) are used to handle escaping on non-word characters. While they are not required in this case, I've gotten into the habit of including them whenever I copy a string into a regular expression. If the expression does not match (unless is the opposite of if), next is executed (Statement Modifiers).
    4. Concatenate the result onto $result_1 (Assignment Operators).

    Result 2 functions similarly to result 1 with the addition of a substitution. s/^((?:\S+\s+){3})\S+/${1}Bob/; can be broken down as follows:

    1. Start at the beginning of the string (^)
    2. Capture ((...)) three copies ((?:...){3}) of one or more non-whitespace characters (\S+) followed by one or more whitespace characters (\s+) into the first buffer.
    3. Match one or more non-whitespace characters (\S+)
    4. Replace everything that matched with the contents of the first buffer (${1}) followed by Bob

    I hope this is clear. See perlre or perlretut for more info on building regular expressions. For the future, try to include sample input and expected output, wrapped in code tags, so we have something test our code against. Good luck.

      Thanks for the info, it's definitely useful. In an effort to simplify my question, here's some background info on what I'm doing, how I'm getting the data, etc. We use an application to manage network devices. It has a series of APIs, some are useful, some not so much. This one gives us the data but it's in an array that seems really difficult to parse / pull data out of. I'm going to focus on just one example, hopefully I'll learn this and be able to apply it to the other cases. I'm working on understanding the code that was suggested, but I think it should work for either case - one result or many results. So, our one case looks like this:

      $VAR1 = [ 'snmp-server host 10.234.171.38 abcd snmp-server host 10.234.171.39 abcd snmp-server host 10.234.171.40 abcd !snmp-server host 10.10.10.1 xyz !' ];

      What I need is the lines that starts with 'snmp-server host' and I'd need them placed in a string. Start off each instance with the word 'no ' and finish each instance with a return:

      no snmp-server host 10.234.171.38 abcd\nno snmp-server host 10.234.171 +.39 abcd\nno snmp-server host 10.234.171.40 abcd\n

      When I run the suggested code (I removed the result 2 section for now), I get the following:

      $VAR1 = [ 'snmp-server host 208.234.171.38 JCIPPUBL no cdp advertise-v2 no cdp run !' ]; Use of uninitialized value in concatenation (.) or string at replace_e +x10.pl line 34. ---Result 1---

      using this code:

      my $result_1; for (split /(?<=\n)/, $res->result()) { next unless /^\Qsnmp-server host\E/; $result_1 .= $_; } print "---Result 1---\n$result_1\n\n";

      Is it odd that the error (line) is the one printing the value? It's as if the variable result_1 isn't getting any data? I have a feeling that the issue is with the array, as I've had other problems in the past trying to do other things with the data. In the past I used map, I considered split or just a substitution, but I can't seem to get just the data I want - either too much or too little. thanks, Chris

        You are getting the uninitialized value warning because $result_1 is undef when fed into print. The real issue is that you are never executing the line $result_1 .= $_;. There are two possibilities I can think of for why this might happen: $res->result() might not return a string as I've assumed or $res->result() is stateful and does not return the same thing on subsequent invocations. I do not have access to documentation on Opsware::NAS::Client, so I can only guess. Two tests you may consider would be running the output through a simple print to make sure you are getting what you expect (print for split /(?<=\n)/, $res->result();) and storing the value in a scalar and feeding that into Data::Dumper (print Dumper $_ = $res->result()).

        I copied your Data::Dumper output and filtering loop in to the following code:

        #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my $VAR1 = [ 'snmp-server host 10.234.171.38 abcd snmp-server host 10.234.171.39 abcd snmp-server host 10.234.171.40 abcd !snmp-server host 10.10.10.1 xyz !' ]; my $result_1; for (split /(?<=\n)/, $VAR1->[0]) { next unless /^\Qsnmp-server host\E/; $result_1 .= $_; } print "---Result 1---\n$result_1\n\n";

        which gives me the result

        ---Result 1--- snmp-server host 10.234.171.38 abcd snmp-server host 10.234.171.39 abcd snmp-server host 10.234.171.40 abcd

        Does this match your expectation?