my $data = '[-3|1|29x250+46+26|200+300+544|Get]' . '[-3|1|29x250+46+26|200+300+444|Get]' . '[-3|1|29x250+34#$%#$INVALID4|Get]' . '[-3|1|29x250+46+26|200+300+244|Get]' . '[#$(GARBAGE'; while ($data =~ /\G \[ (?: ([^|]*) \| ([^|]*) \| (\d+) x (\d+) \+ (\d+) \+ (\d+) \| (\d+) \+ (\d+) \+ (\d+) \| ([^|]*) | (.*?) ) \]/xgc) { if (defined $1) { say "Found record: $1, $2, $3, $4, $5, $6, $7, $8, $9, $10"; } else { say "WARNING: Skipping invalid record: $11"; } } if (pos $data != length $data) { say "WARNING: Could not extract records from remaining input: ", substr($data, pos $data); } pos($data) = undef; #### Found record: -3, 1, 29, 250, 46, 26, 200, 300, 544, Get Found record: -3, 1, 29, 250, 46, 26, 200, 300, 444, Get WARNING: Skipping invalid record: -3|1|29x250+34#$%#$INVALID4|Get Found record: -3, 1, 29, 250, 46, 26, 200, 300, 244, Get WARNING: Could not extract records from remaining input: [#$(GARBAGE