Чтобы соответствовать 1, 2 или 4 элементам, ERE следует изменить следующим образом:
s1="1,2,3,4" ;\
s2="1,2,3" ;\
s3="1" ;\
sP='^[1-9][0-9]{0,},$|^(([1-9][0-9]{0,},){2}){1,2}$' ;\
[[ "${s1}," =~ $sP ]] && printf "\$s1, matches\n" ;\
[[ "${s2}," =~ $sP ]] || printf "\$s2, does not match\n" ;\
[[ "${s3}," =~ $sP ]] && printf "\$s3 matches\n"
Ваш оригинальный ERE может быть описан итеративно:
[1-9][0-9]{0,},
соответствует 1, или 2, или 3, или 432, и т.д.
([1-9][0-9]{0,},){1,2}
соответствует любой одной или двум последовательным последовательностям, описанным выше: 1, или 3, или 1,2, или 10, или 10 432 и т.д.
(([1-9][0-9]{0,},){1,2}){1,2}
соответствует любому 1 или 2 вхождениям последней последовательности 1, или 1,2, или 1,2 3 и т.д.