Re: Parse variables from @output
by roboticus (Chancellor) on Nov 14, 2019 at 20:55 UTC
|
Cisco_Dave:
You don't specify what's wrong, so I can only guess: I'm thinking that line 15 should be:
$details{'Main Memory'} = $1 if (/^\S+ Intel (\S+)/i);
You have only one capture group (i.e., part of the regular expression inside parenthesis), so the captured value can only be in $1. For example:
$ cat fluffy.pl
use strict;
use warnings;
my $t = "Now is the time for all good men to come to the aid";
if ($t =~ /^(\w+) (\w+) (\w+) (\w+) (\w+) (\w+)/) {
print "Words: 2='$2', 4='$4', 1='$1'\n";
}
else {
print "*** no match! ***\n";
}
when you run it, you should get:
$ perl fluffy.pl
Words: 2='is', 4='time', 1='Now'
In order to get better answers, it's helpful to include a bit more information. Especially if you can make a simple bit of code that can demonstrate the problem as I just did here. I hope I guessed correctly, but if not, update the code in your original question to make it clear. You could do so by putting something like:
use strict;
use warnings;
my @output = (
"a few lines of data that I cut\n",
"and pasted from a screen capture that I want to\n",
"process.\n",
);
at the front, and something like:
print "Chassis: <$details{'Chassis'}>\n";
print "Main Memory: <$details{'Main Memory'}>\n";
at the end to show what you actually get. Then specify what you actually wanted instead, so we can clearly see the problem. Note the angle brackets I put in the output: whitespace handling errors (especially newlines and carriage returns) are so common that it's helpful to put something before and after the string so you can see if there are unwanted characters in your output.
...roboticus
When your only tool is a hammer, all problems look like your thumb. | [reply] [d/l] [select] |
|
|
Thanks for the quick reply. Will fully read and understand fully tomorrow. Have edited original post to help clarify a little.
| [reply] |
Re: Parse variables from @output
by BillKSmith (Monsignor) on Nov 14, 2019 at 23:34 UTC
|
You have provided your input (strangely called '@output') only as comments. We cannot tell exactly how this is broken into array elements or how those elements are broken into lines. Please post code that we can run and actually see the results that are correct and duplicate your problem. The following code should get you started. Please correct errors I may have made in understanding your data.
use strict;
use warnings;
use Data::Dumper;
my @output = (
qq/"Hardware\n/
.qq/"cisco Nexus 3048 Chassis ("48x1GE + 4x10G Supervisor")\n/
.qq/Intel(R) Celeron(R) CPU P450 with 3981680 kB of memory.\n/
,
qq/Cisco CISCO2901\/K9 (revision 1.0)/
.qq/ with 483328K\/40960K bytes of memory.\n/
,
qq/cisco WS-C3550-48 (PowerPC) processor (revision N0)/
.qq/ with 65526K\/8192K bytes of memory.\n/
.qq/Model number: WS-C3550-48-SMI\n/
);
foreach (@output) {
my %details;
if (/^Hardware/i) {
$details{'Chassis'} = $1 if (/^cisco Nexus (\S+)/i);
$details{'Main Memory'} = $1 if (/^Intel (\S+)/i);
}
if (/^cisco ((Catalyst )?\S+) .* with (\S+) bytes of memory/i) {
$details{'Chassis'} = $1;
$details{'Main Memory'} = $3;
}
$details{'Chassis'} = $1 if (/^Model number: (\S+)/i);
print Dumper(\%details);
}
| [reply] [d/l] |
|
|
Yes that's on the right lines Bill thanks. Will test again tomorrow.
Essentially in this example there are three different contents for @output depending on the type of device the show ver command is run on. Each if statement determines which of the three it is, i.e. if there is a regex match for the line it uses that version of @output and sets the variables for chassis and memory from the output there
| [reply] |
|
|
Still struggling, update in main thread :(
| [reply] |
Re: Parse variables from @output
by NetWallah (Canon) on Nov 14, 2019 at 23:48 UTC
|
See if this extendable (declarative) coding style works for you:
use strict;
use warnings;
my %details;
my @rules=(
"Hardware" => sub{$details{HARDWARE_SEEN} = 1 },
'cisco Nexus (\S+)' => sub{return 0 unless $details{HARDWARE_SEEN};
$details{Chassis} = $_[0]; },
'Intel.+?(\d+)\s*(\w{2}) of memory'
=> sub{
return 0 unless $details{HARDWARE_SEEN}
+;
$details{"Main Memory"} = $_[0];
$details{"Main Memory Unit"} = $_[1];
},
);
while (<DATA>){
for (my $i=0; $i < $#rules; $i+=2){
my $regex=qr|$rules[$i]|;
my $action = $rules[$i+1];
next unless m/$regex/i;
last if $action->($1,$2,$3);
}
}
for (sort keys %details){
print "$_\t = $details{$_}\n";
}
__DATA__
# Sample output
# Hardware
# cisco Nexus 3048 Chassis ("48x1GE + 4x10G Supervisor")
# Intel(R) Celeron(R) CPU P450 with 3981680 kB of memory.
Output:
Chassis = 3048
HARDWARE_SEEN = 1
Main Memory = 3981680
Main Memory Unit = kB
Feel free to post questions about the code here.
"From there to here, from here to there, funny things are everywhere." -- Dr. Seuss
| [reply] [d/l] [select] |
|
|
| [reply] |
Re: Parse variables from @output
by Cisco_Dave (Acolyte) on Nov 15, 2019 at 08:13 UTC
|
#!/usr/local/bin/perl
##
use strict;
use warnings;
use Data::Dumper;
my @output = (
qq/Hardware\n/
.qq/" cisco Nexus 3048 Chassis ("48x1GE + 4x10G Supervisor)"\n/
.qq/" Intel(R) Celeron(R) CPU P450 with 3981680 kB of memory."\n/
,
qq/"Cisco CISCO2901\/K9 (revision 1.0) with 483328K\/40960K bytes
+ of memory."\n/
,
qq/"cisco WS-C3550-48 (PowerPC) processor (revision N0) with 6552
+6K\/8192K bytes of memory."\n/
.qq/"Model number: WS-C3550-48-SMI"\n/
);
foreach (@output) {
my %details;
if (/^Hardware/i) {
$details{'Chassis'} = $1 if (/^cisco Nexus (\S+)/i);
$details{'Main Memory'} = $1 if (/^Intel (\S+)/i);
}
if (/^cisco ((Catalyst )?\S+) .* with (\S+) bytes of memory/i) {
$details{'Chassis'} = $1;
$details{'Main Memory'} = $3;
}
$details{'Chassis'} = $1 if (/^Model number: (\S+)/i);
print Dumper(\%details);
}
Result...
$VAR1 = {};
$VAR1 = {};
$VAR1 = {};
Result needs to be...
$VAR1 = {
'Main Memory' => '3981680',
'Chassis' => '3048'
};
$VAR1 = {
'Main Memory' => '483328K/40960K',
'Chassis' => 'CISCO2901/K9'
};
$VAR1 = {
'Main Memory' => '65526K/8192K',
'Chassis' => 'WS-C3550-48'
};
| [reply] [d/l] [select] |
Re: Parse variables from @output
by Cisco_Dave (Acolyte) on Nov 15, 2019 at 08:40 UTC
|
Removed the quotation marks to fix second and third values for $VAR1. Just need to figure out the first result now, note the two leading spaces are intentional below, this is how it appears in the output
#!/usr/local/bin/perl
##
use strict;
use warnings;
use Data::Dumper;
my @output = (
qq/Hardware\n/
.qq/ cisco Nexus 3048 Chassis ("48x1GE + 4x10G Supervisor)\n/
.qq/ Intel(R) Celeron(R) CPU P450 with 3981680 kB of memory.\n/
,
qq/Cisco CISCO2901\/K9 (revision 1.0) with 483328K\/40960K bytes
+of memory.\n/
,
qq/cisco WS-C3550-48 (PowerPC) processor (revision N0) with 65526
+K\/8192K bytes of memory.\n/
.qq/Model number: WS-C3550-48-SMI\n/
);
print "@output\n";
foreach (@output) {
my %details;
if (/^Hardware/i) {
$details{'Chassis'} = $1 if (/^cisco Nexus (\S+)/i);
$details{'Main Memory'} = $1 if (/^Intel (\S+)/i);
}
if (/^cisco ((Catalyst )?\S+) .* with (\S+) bytes of memory/i) {
$details{'Chassis'} = $1;
$details{'Main Memory'} = $3;
}
$details{'Chassis'} = $1 if (/^Model number: (\S+)/i);
print Dumper(\%details);
}
Result...
Hardware
cisco Nexus 3048 Chassis ("48x1GE + 4x10G Supervisor)
Intel(R) Celeron(R) CPU P450 with 3981680 kB of memory.
Cisco CISCO2901/K9 (revision 1.0) with 483328K/40960K bytes of memory
+.
cisco WS-C3550-48 (PowerPC) processor (revision N0) with 65526K/8192K
+ bytes of memory.
Model number: WS-C3550-48-SMI
$VAR1 = {};
$VAR1 = {
'Main Memory' => '483328K/40960K',
'Chassis' => 'CISCO2901/K9'
};
$VAR1 = {
'Main Memory' => '65526K/8192K',
'Chassis' => 'WS-C3550-48'
};
| [reply] [d/l] [select] |
|
|
.qq/ cisco Nexus 3048 Chassis ("48x1GE + 4x10G Supervisor)\n/
but your match wants cisco to appear at the start of a line:
$details{'Chassis'} = $1 if (/^cisco Nexus (\S+)/i);
You will need to allow for some whitespace in front of cisco, for example by allowing for \s*:
$details{'Chassis'} = $1 if (/^\s*cisco Nexus (\S+)/i);
But "start of the line" (^) means "start of the whole string" to Perl unless you also tell it to match after a newline using the /m modifier:
$details{'Chassis'} = $1 if (/^\s*cisco Nexus (\S+)/mi);
Adding that, I get:
$VAR1 = {
'Chassis' => '3048'
};
$VAR1 = {
'Main Memory' => '483328K/40960K',
'Chassis' => 'CISCO2901/K9'
};
$VAR1 = {
'Chassis' => 'WS-C3550-48',
'Main Memory' => '65526K/8192K'
};
| [reply] [d/l] [select] |
|
|
$details{'Main Memory'} = $1 if (/^\s* Intel .* with (\S+) kB of memor
+y/mi);
| [reply] [d/l] |
|
|
|
|
Re: Parse variables from @output
by Cisco_Dave (Acolyte) on Nov 15, 2019 at 12:18 UTC
|
Have expanded the variables further to fix more issues now.
#!/usr/local/bin/perl
##
use strict;
use warnings;
use Data::Dumper;
my @output = (
qq/Software\n/
.qq/ BIOS: version 3.6.0\n/
.qq/ kickstart: version 7.1(5)N1(1)\n/
.qq/ system: version 7.1(5)N1(1)\n/
.qq/ kickstart image file is: bootflash:\/\/\/n5000-uk9-kickstart
+.7.1.5.N1.1.bin\n/
.qq/ system image file is: bootflash:\/\/\/n5000-uk9.7.1.5.N1.
+1.bin\n/
.qq/Hardware\n/
.qq/ cisco Nexus 5548 Chassis ("O2 32X10GE\/Modular Universal Pla
+tform Supervisor")\n/
.qq/ Intel(R) Xeon(R) CPU with 8253840 kB of memory.\n/
.qq/ Processor Board ID FOC163849D1\n/
.qq/ Device name: tpecasw01\n/
.qq/ bootflash: 2007040 kB\n/
.qq/Kernel uptime is 636 day(s), 1 hour(s), 34 minute(s), 49 secon
+d(s)\n/
);
print "@output\n";
foreach (@output) {
my %details;
if (/^Hardware/mi) {
$details{'Chassis'} = $1 if (/^\s*cisco Nexus (\S+) Chassi
+s/mi);
$details{'Main Memory'} = $1 if (/^\s*Intel.* with (\S+) kB of
+ memory/mi);
$details{'Name'} = $1 if (/^\s*Device name: (\S+)/mi);
$details{'Uptime'} = $1 if (/^\s*Kernel uptime is (.*?)\s*$/mi
+);
$details{'Version'} = $1 if (/^\s*system: .*version (\S+?)[,\s
+]/mi);
$details{'IOS File'} = $1 if (/^\s*system image file is:\s*"(.
+*)"/mi);
$details{Serial} = $1 if (/^\s*Processor board ID (\S+)/mi);
$details{'ROM Version'} = $1 if (/^\s*BIOS: .*version (\S+?)[,
+\s]/mi); # aka BIOS
$details{'Boot Version'} = $1 if (/^\s*kickstart: .*version (\
+S+?)[,\s]/mi); # aka kickstarter
$details{'Boot Flash'} = $1 if (/^\s*bootflash: (\S+)/mi);
}
print Dumper(\%details);
}
All are working apart from $details('IOS File') is not populating/displaying. Any ideas? Result should be bootflash:///n5000-uk9.7.1.5.N1.1.bin
Value for 'IOS File' missing in results...
Software
BIOS: version 3.6.0
kickstart: version 7.1(5)N1(1)
system: version 7.1(5)N1(1)
kickstart image file is: bootflash:///n5000-uk9-kickstart.7.1.5.N1.1
+.bin
system image file is: bootflash:///n5000-uk9.7.1.5.N1.1.bin
Hardware
cisco Nexus 5548 Chassis ("O2 32X10GE/Modular Universal Platform Sup
+ervisor")
Intel(R) Xeon(R) CPU with 8253840 kB of memory.
Processor Board ID FOC163849D1
Device name: tpecasw01
bootflash: 2007040 kB
Kernel uptime is 636 day(s), 1 hour(s), 34 minute(s), 49 second(s)
$VAR1 = {
'Uptime' => '636 day(s), 1 hour(s), 34 minute(s), 49 second(
+s)',
'Serial' => 'FOC163849D1',
'Version' => '7.1(5)N1(1)',
'ROM Version' => '3.6.0',
'Main Memory' => '8253840',
'Name' => 'tpecasw01',
'Boot Version' => '7.1(5)N1(1)',
'Chassis' => '5548'
};
| [reply] [d/l] [select] |
|
|
system image file is: bootflash:\/\/\/n5000-uk9.7.1.5.N1.1.bin
+\n
/^\s*system image file is:\s*"(.*)"/mi
Maybe you want to use a more interactive tool to find where your regex fails, for example haukex's interactive Perl regex tester. | [reply] [d/l] |
|
|
Already tried that one, doesn't work I'm afraid
| [reply] |
|
|
|
|