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
\n
each 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
%interfaces
hash 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