$input = q|http://abc.org,http://de,f.org,https://ghi.org|; #### @captures = ( 'http://abc.org', 'http://de,f.org', 'https://ghi.org', ); #### @captures = ( 'http://abc.org', 'http://de,f.org', ); #### use strict; use warnings; use 5.010_001; use Test::More; my @raw_inputs = ( 'http://abc.org', 'http://de,f.org', 'https://ghi.org', 'http://jkl.org', ); my @inputs = ( $raw_inputs[0] ); for my $q (1..3) { push @inputs, join(',' => @raw_inputs[0..$q]); } is_deeply( _recognize_limited_urls($inputs[0], 3), [ $raw_inputs[0] ], "1 URL", ); is_deeply( _recognize_limited_urls($inputs[1], 3), [ @raw_inputs[0..1] ], "2 URLs (one containing a comma)", ); is_deeply( _recognize_limited_urls($inputs[2], 3), [ @raw_inputs[0..2] ], "3 URLs (one containing a comma)", ); is_deeply( _recognize_limited_urls($inputs[3], 3), [ @raw_inputs[0..2] ], "Still only 3 URLs (one containing a comma); reject those over max", ); done_testing(); sub _recognize_limited_urls { my ($input, $max) = @_; my $str = $input; my $pattern = qr/^(http.*?)(?:,(http.*?))?$/; my $count = 0; my @captures = (); LOOP: while ($count < $max) { my ($capture, $balance); if ($str and $str =~ m/$pattern/) { ($capture, $balance) = ($1, $2); push @captures, $capture; $str = $balance; $count++; } else { last LOOP; } } return \@captures; }