for ( reverse 1..20 ) { $re .= sprintf "\\d{%d} {%d}|", $_, 20-$_; } chop $re; $re = qr/^(?:$re)$/; print $re, $/; @tests = ( '01234567890123456789', # OK '123 ', # OK '123 ', # NOK '123 123 ', # NOK ' ', # NOK '123c ', # NOK ); for(@tests){ print m/$re/ ? "'$_' #OK\n" : "'$_' #NOK\n" } __DATA__ (?-xism:^(?:\d{20} {0}|\d{19} {1}|\d{18} {2}|\d{17} {3}|\d{16} {4}|\d{15} {5}|\d{14} {6}|\d{13} {7}|\d{12} {8}|\d{11} {9}|\d{10} {10}|\d{9} {11}|\d{8} {12}|\d{7} {13}|\d{6} {14}|\d{5} {15}|\d{4} {16}|\d{3} {17}|\d{2} {18}|\d{1} {19})$) '01234567890123456789' #OK '123 ' #OK '123 ' #NOK '123 123 ' #NOK ' ' #NOK '123c ' #NOK