use warnings; use strict; sub parse { local $_ = shift; my @out = (''); pos=undef; while (1) { if ( m{\G , }xgc ) { push @out, '' } elsif ( m{\G \\x([0-9a-fA-F]{2}) }xgc ) { $out[-1] .= chr hex $1 } elsif ( m{\G (?| \\([,\\]) | ([^,\\]+) ) }xgc ) { $out[-1] .= $1 } else { last } } pos==length or die "parse of '$_' failed at pos ".pos; return @out; } use Test::More tests=>1; my @o = parse "1,Something\\,\\\\text\\\\text\\x2B\\\\,X,99"; is_deeply \@o, ["1","Something,\\text\\text+\\","X","99"];