use strict; use warnings; use Data::Dumper; my $state = { started => 0, current_port_channel => undef, inside_ports_item => 0 }; my $data = { port_channel => {} }; while () { chomp; $state->{started}++ and next if /--- show port-channel database ---/; next unless $state->{started}; if (/^port-channel (\d+)/) { $data->{port_channel}->{$1} = {}; $state->{current_port_channel} = $1; next; } if ( $state->{current_port_channel} ) { if (/^\s+Ports:\s+(\S+)\s+\[(.+?)]/) { push @{ $data->{port_channel}->{ $state->{current_port_channel} }->{port_member} }, $1; # play with $2 ("up", "down", if you want to) $state->{inside_ports_item} = 1; next; } if ( $state->{inside_ports_item} and /^\s+(\S+)\s+\[(.+?)]/ ) { push @{ $data->{port_channel}->{ $state->{current_port_channel} }->{port_member} }, $1; next; } } } ### while () print Dumper $data; __DATA__ -------------------- show port-channel database ------------------ port-channel 1 Administrative channel mode is on Operational channel mode is on Last membership update succeeded First operational port is fc1/5 2 ports in total, 2 ports up Ports: fc2/5 [up] fc1/5 [up] * port-channel 3 Administrative channel mode is on Operational channel mode is on Last membership update succeeded First operational port is fc1/1 1 port in total, 1 port up Ports: fc1/1 [up] * ****************************************************************** #### $VAR1 = { 'port_channel' => { '1' => { 'port_member' => [ 'fc2/5', 'fc1/5' ] }, '3' => { 'port_member' => [ 'fc1/1' ] } } };