Как указано в чате, если возможная комбинация длиннее 7, она должна игнорироваться, и никакие ее части не заменяются. Посмотреть этот чат .
Моя обратная ссылка бесплатное решение:
s/
(?:(?<!a)a|(?<!t|a)t)
(?:(?<=a)a|(?<=a)t|(?<=t)t){3,6}
(?!(?<=a)a|(?<=a)t|(?<=t)t)
/\U$&/gix;
С некоторыми комментариями:
s/
# match the first [at] only if not part of a valid sequence
(?:(?<!a)a|(?<!t|a)t)
# only match the allowed transitions: a->a, a->t, t->t
(?:(?<=a)a|(?<=a)t|(?<=t)t){3,6}
# ending can not be a valid transition: negate the above
(?!(?<=a)a|(?<=a)t|(?<=t)t)
/\U$&/gix;
Обновление: Применил идеи сокращения Джейкобом, здесь с некоторыми комментариями:
s/
# match the first a or t only if it's not part of a valid sequence
(?:(?<!a)a|(?<!t|a)t)
# only match the allowed transitions: a->a, a->t, t->t
# (t can follow any of the previous chars, so no need to check it)
(?:(?<=a)a|t){3,6}
# ending can not be a valid transition: negate the above
(?!(?<=a)a|t)
/\U$&/gix;
Редактировать : решение с меньшими регулярными выражениями, просто для удовольствия:
s/(a+t*|t+)/(length $1 >= 4 && length $1 <= 7)? "\U$1": $1/gie;
PS: Спасибо OP за более интересный, чем обычно, вопрос регулярных выражений. :)