use strict; use warnings; use Data::Dumper; $Data::Dumper::Sortkeys = 1; my $string = q{AA(aa),AB(a(b),b),AC(Departament d'Astronomia i Astrofísica. Universitat de València. C/Dr. Moliner 50, 46100 Burjassot (València), Spain),AD(a,c,XX(ignored!)),AE(Neumann,AE(+++)),AF(FAILS in rare case where value contains next token (here:AG),AG(blah)),AG(last)}; my $range = join(',', 'A'..'Z'); my %result; for (my $key = 'AA'; $key ne 'AAA'; $key++) { # AA..ZZ last if $string !~ /(?:^|\),)$key\(/; # stop if xx( or ),xx( missing my $key2 = $key; $key2++; # match AA(...),BB( if ( $string =~ / $key \( (.*?) \) (?: ,$key2\( | $) /x ) { $result{ $key } = $1; } else { #TODO: Error handling warn "No match for $key(...),$key2!\n"; } } print "Result from '$string':\n", Dumper( \%result ), "\n"; __DATA__ $VAR1 = { 'AA' => 'aa', 'AB' => 'a(b),b', 'AC' => 'Departament d\'Astronomia i Astrofísica. Universitat de València. C/Dr. Moliner 50, 46100 Burjassot (València), Spain', 'AD' => 'a,c,XX(ignored!)', 'AE' => 'Neumann,AE(+++)', 'AF' => 'FAILS in rare case where value contains next token (here:AG', 'AG' => 'blah)),AG(last' };