regex - Parsing (partially) non-uniform text blocks in Perl -
i have file few blocks in file (and in variable, @ point in program).
vlan2 up, line protocol .... reliability 255/255, txload 1/255, rxload 1/255^m .... last clearing of "show interface" counters 49w5d input queue: 0/75/0/0 (size/max/drops/flushes); total output drops: 0 .... l3 out switched: ucast: 17925 pkt, 23810209 bytes mcast: 0 pkt, 0 bytes 33374 packets input, 13154058 bytes, 0 no buffer received 926 broadcasts (0 ip multicasts) 0 runts, 0 giants, 0 throttles 0 input errors, 0 crc, 0 frame, 0 overrun, 0 ignored 3094286 packets output, 311981311 bytes, 0 underruns 0 output errors, 0 interface resets 0 output buffer failures, 0 output buffers swapped out
here's second block, show how blocks can vary:
port-channel86 down (no operational members) ... reliability 255/255, txload 1/255, rxload 1/255 ... last clearing of "show interface" counters 31w2d ... rx 147636 unicast packets 0 multicast packets 0 broadcast packets 84356 input packets 119954232 bytes 0 jumbo packets 0 storm suppression packets 0 runts 0 giants 0 crc 0 no buffer 0 input error 0 short frame 0 overrun 0 underrun 0 ignored 0 watchdog 0 bad etype drop 0 bad proto drop 0 if down drop 0 input dribble 0 input discard 0 rx pause tx 147636 unicast packets 0 multicast packets 0 broadcast packets 84356 output packets 119954232 bytes 0 jumbo packets 0 output error 0 collision 0 deferred 0 late collision 0 lost carrier 0 no carrier 0 babble 0 output discard 0 tx pause 0 interface resets
i want pick out data elements each block, may or may not exist in each block. example, in first block posted may want know there 0 runts, 0 input errors , 0 overrun. in second block, might want know there 0 jumbo packets, collisions, etc. if given query isn't in block, it's acceptable return na, designed processed uniformly.
each block structured in similar way 2 posted; newlines , spaces delimiting entries, commas delimiting others.
i have few ideas how might work. i'm unaware if there kind of "look back" function in perl, attempt field names (runts, "input errors", etc) , grab previous integer; seems elegant solution this, i'm unsure if it's possible.
currently, i'm doing in perl. each "block" i'm processing several of these blocks (separated double newlines). doesn't have done in single regular expressions; believe can done applying several regular expressions per block. performance not factor, script run maybe once per hour.
my goal of .csv file (or other data format that's graphable) in automated fashion.
any ideas?
edit: example output in csv mentioned, written line line (for multiple entries this) file end result. if particular entry isn't found in block, marked na in corresponding line:
interface_name,txload,rxload,last_clearing,input_queue,output_drops,runts,.... vlan2,1,1,49w5d,0-75-0-0,0,0,.... port-channel86,1,1,31w2d,na,na,0,...
simple hash of properties , numbers.
sub extract { ($block) = @_; %r; while ($block =~ /(?<num>\d+) \s (?<name>[a-za-z\s]+)/gmsx) { $name = $+{name}; $num = $+{num}; $name =~ s/\a \s+//msx; $name =~ s/\s+ \z//msx; $r{$name} = $num; } return %r; } $block = <<''; vlan2 up, line protocol ⋮ $block2 = <<''; port-channel86 down (no operational members) ⋮ use data::dumper qw(dumper); print dumper {extract $block}; print dumper {extract $block2};
Comments
Post a Comment