my $pat = q{ ^([A-Z]+)$ # $1 global model name | ( # $2 optional model name [A-Z]+ )? (.+)$ # $3 the rest of line }; my @stack; while( $input =~ m{$pat}gmsx ){ my @token; if( $1 ){ push @token, ['global_model', $1 ]; } if( $2 ){ push @token, [ 'model', $1 ]; } if( $3 ){ push @token, [ 'pairs', split /\|/, "$3" ]; } push @stack, \@token; } use Data::Dump qw/ dd /; dd( \@stack ); __END__