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

After getting great help before, I'm back for more. This time I'm working with a similar but different array. I need to do a few things here.... 1) I need to pull any / all lines that start with 'snmp-server host' and stick them into a variable and have this variable formatted as one long line of multiple lines - it'd look similar to this: snmp-server host 10.234.171.46 admin\nsnmp-server host 10.234.171.51 admin frame-relay config snmp\nsnmp-server host 10.234.171.75 admin\n 2) I need to substitute the 4th word in the line(s) starting with 'snmp-server' that is separated by spaces and make it 'Bob' and stick this in a variable, and format it the same as with #1 3) I need to substitute 'snmp-server' with 'no snmp-server' and stick this in a variable I can get #1 & #3 to work if there's just one occurrance in the array, but if there's more than one, then I just get the first one. Any suggestions for any parts would be awesome. thanks, Chris

So, the output from my code could look like: $VAR1 = [ 'snmp-server host 10.234.171.38 JCIPPUBL no cdp advertise-v2 no cdp run !' ]; server host 10.234.171.38 abcd no snmp-server host 10.234.171.38 abcd \n or there can be multiple lines such as this: $VAR1 = [ 'snmp-server host 10.234.171.45 admin snmp-server host 10.234.171.46 admin snmp-server host 10.234.171.51 admin frame-relay config snmp snmp-server host 10.234.171.75 admin snmp-server host 10.234.171.51 publ frame-relay config snmp snmp-server host 10.234.171.54 publ frame-relay config snmp snmp-server host 10.234.171.59 publ !snmp-server host 10.234.171.46 admin snmp-server host 10.234.171.51 admin frame-relay config snmp snmp-server host 10.234.171.75 admin snmp-server host 10.234.171.51 publ frame-relay config snmp snmp-server host 10.234.171.54 publ frame-relay config snmp snmp-server host 10.234.171.59 publ !snmp-server host 10.234.171.51 admin frame-relay config snmp snmp-server host 10.234.171.75 admin snmp-server host 10.234.171.51 publ frame-relay config snmp snmp-server host 10.234.171.54 publ frame-relay config snmp snmp-server host 10.234.171.59 publ !snmp-server host 10.234.171.75 admin snmp-server host 10.234.171.51 publ frame-relay config snmp snmp-server host 10.234.171.54 publ frame-relay config snmp snmp-server host 10.234.171.59 publ !snmp-server host 10.234.171.51 publ frame-relay config snmp snmp-server host 10.234.171.54 publ frame-relay config snmp snmp-server host 10.234.171.59 publ !snmp-server host 10.234.171.54 publ frame-relay config snmp snmp-server host 10.234.171.59 publ !snmp-server host 10.234.171.59 publ !' ]; server host 10.234.171.45 admin no snmp-server host 10.234.171.45 admin \n The code is currently: #!/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()])); foreach my $var1 ($res->result()) { #my ($image) = $var1 =~ /^SystemImage:\s*([^\n]+)/m my ($snmp) = $var1 =~ /^snmp-\s*([^\n]+)/m or die("No SystemImage\n"); print("$snmp\n"); my ($no_snmp) = 'no snmp-' . $snmp . '\n'; print("$no_snmp\n"); } $nas->logout();

Replies are listed 'Best First'.
Re: pulling more data from an array
by kennethk (Abbot) on Aug 04, 2010 at 20:36 UTC
    That's all quite lovely - I'd like a puppy. While there are plenty of people here who are happy to help, the tone I get from your message is that you want us to do your work for you. I assume that this is unintentional, but please be cognizant of how you ask questions in the future. See How do I post a question effectively?.

    Also note the material you posted is far more complicated than it need be - you are using 7 different modules and have strict commented out when you really just need know how to process your sample input. You also can include multiple instances of <code> tags in one post, and this can really aid in clarity.

    I don't understand what you mean by case 3 (an example is worth 1,000 words) but everything else you ask can be done in a fairly straight-forward fashion using regular expressions and Loop Control. I've crafted up some simple treatments, where I've assumed $res->result() returns a scalar string as indicated by your Data::Dumper output. If anything is unclear, I'll be happy to clarify:

    #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my $data = do{local $/; <DATA>}; print Dumper([$data]), "\n\n"; my $result_1; for (split /(?<=\n)/, $data) { next unless /^\Qsnmp-server host\E/; $result_1 .= $_; } print "---Result 1---\n$result_1\n\n"; my $result_2; for (split /(?<=\n)/, $data) { next unless /^\Qsnmp-server\E/; s/^((?:\S+\s+){3})\S+/${1}Bob/; $result_2 .= $_; } print "---Result 2---\n$result_2\n\n"; __DATA__ snmp-server host 10.234.171.45 admin snmp-server host 10.234.171.46 admin snmp-server host 10.234.171.51 admin frame-relay config snmp snmp-server host 10.234.171.75 admin snmp-server host 10.234.171.51 publ frame-relay config snmp snmp-server host 10.234.171.54 publ frame-relay config snmp snmp-server host 10.234.171.59 publ !snmp-server host 10.234.171.46 admin snmp-server host 10.234.171.51 admin frame-relay config snmp snmp-server host 10.234.171.75 admin snmp-server host 10.234.171.51 publ frame-relay config snmp snmp-server host 10.234.171.54 publ frame-relay config snmp snmp-server host 10.234.171.59 publ !snmp-server host 10.234.171.51 admin frame-relay config snmp snmp-server host 10.234.171.75 admin snmp-server host 10.234.171.51 publ frame-relay config snmp snmp-server host 10.234.171.54 publ frame-relay config snmp snmp-server host 10.234.171.59 publ !snmp-server host 10.234.171.75 admin snmp-server host 10.234.171.51 publ frame-relay config snmp snmp-server host 10.234.171.54 publ frame-relay config snmp snmp-server host 10.234.171.59 publ !snmp-server host 10.234.171.51 publ frame-relay config snmp snmp-server host 10.234.171.54 publ frame-relay config snmp snmp-server host 10.234.171.59 publ !snmp-server host 10.234.171.54 publ frame-relay config snmp snmp-server host 10.234.171.59 publ !snmp-server host 10.234.171.59 publ !

      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

        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.

Re: pulling more data from an array
by aquarium (Curate) on Aug 05, 2010 at 03:21 UTC
    Just have a feeling that you're overcomplicating the nature of the problem. Are you just trying to replace pub1 or admin with Bob and then join some lines?
    the hardest line to type correctly is: stty erase ^H