regex - Parsing data with perl- capturing a range of text -
i'm writing code parse interfaces on network, looking configurations.. etc.
the data looks this:
interface fa1 mode access port-security mac-address sticky ! interface fa2 mode trunk ! basically starting "^interface " , ending "!".
my current algorithm "record" data need
foreach $line (@input) { if ( $line =~ m/^interface.+\d/ && $line !~ m/interface embedded-service-engine|bri|tengigabitethernet|vlan|port-channel|atm|loopback/i) { $record = 1; } #$int ne '' handle rest of file not in format if( $line =~ m/!/ && $int ne '') { #save data in format 'interface fa2,mode trunk' #if interface doesn't have port-security push(@intlist, join(','split("\r\n",$int))."\n") unless $int =~ m/port-security/; $record=0; $int=''; } if ($record) { $int.=$line; } } while works in case, i'd way it. i've searched , found can use range operator '..' on regex
which turns code :
@input # contains file @interfaces = grep (/^interface.+\d/ .. /!/, @input); which gives me interface data, problem every line single element in @interfaces array. how can split data /^interface.+\d/ .. /!/ 1 element in array without creating more loops?
the goal down 1 element can scan interfaces don't want @ interface embedded-service-engine|bri|tengigabit interfaces have correct configurations.
have @ $/ because think that'll help. it's record separator - defaults \n.
then can apply regular expressions current 'chunk' pull out data require - default regular expression/capture group applies $_ implicit variable.
e.g.
#!/usr/bin/perl use strict; use warnings; local $/ = '!'; while ( <data> ) { ( $interface ) = m/interface (\w+)/i; next if $interface =~ m/embedded-service-engine/; ( $mode ) = m/mode (\w+)/; print "$interface $mode\n"; print "---next record---\n"; } __data__ interface fa1 mode access port-security mac-address sticky ! interface fa2 mode trunk ! if need keep data other uses (e.g. 'process go' isn't suitable) tool job hash.
you can either use above - , populate hash particular keys you're interested in - or use magic of map you.
#!/usr/bin/perl use strict; use warnings; use data::dumper; local $/ = '!'; %interfaces; while ( <data> ) { ( $interface ) = m/interface (\w+)/i; next if $interface =~ m/embedded-service-engine/; %interface_values = map { ( $key, $value ) = split; $key, $value || 1 } grep { /\w/ } split ( "\n" ); $interfaces{$interface} = \%interface_values; } print dumper \%interfaces __data__ interface fa1 mode access port-security mac-address sticky ! interface fa2 mode trunk ! that map line basically:
- splits current record on
\neach line. - filters 'not word' values (so blank lines , !)
- splits each line on whitepace, key , value pair.
- if no value defined, sets 1. (so in example,
port-security) - populates hash these key-value pairs.
- and updates
%interfaceshash each interface id.
giving like:
$var1 = { 'fa1' => { 'port-security' => 1, 'mode' => 'access', 'interface' => 'fa1', 'mac-address' => 'sticky' }, 'fa2' => { 'mode' => 'trunk', 'interface' => 'fa2' } };
Comments
Post a Comment