Text::Balanced::extract_bracketed( $str, '[]' ); #### use strict; use warnings; use Text::Balanced qw(extract_quotelike); use Data::Dumper; sub parse_str { my $str = shift; $str =~ s/\A\s*//; # list-like if ($str =~ /\A\s*\[/) { # eat initial [ $str =~ s/\A\s*\[\s*//; my @arr; while ($str !~ /\A\s*\]/) { my ($term, $remainder) = parse_str($str); push @arr, $term; if ($remainder =~ /\A\s*[,\]]/) { $str = $remainder; $str =~ s/\A\s*,\s*//; } else { die "Expected comma; got <<<$remainder>>>"; } } # eat trailing ] $str =~ s/\A\s*\]\s*//; return \@arr, $str; } # quote-like elsif ($str =~ /\A['"]/) { my ($term, $remainder) = extract_quotelike($str); $term =~ s/\A['"]//; $term =~ s/['"]\z//; return ($term, $remainder); } # number-like or bareword-like elsif ($str =~ /\A([\w\.]+)/) { my $term = $1; return ($term, substr($str, length($term))); } die "Expected something else; got <<<$str>>>"; } print Dumper parse_str <