Вы можете использовать
^[A-Za-z](?:[A-Za-z0-9_]*[A-Za-z0-9])?$
, что совпадает с
^[A-Za-z](?:\w*[A-Za-z0-9])?$
См. Демоверсию regex
В Java вы можете использовать его с .matches()
и опускать якоря:
s.matches("[A-Za-z](?:[A-Za-z0-9_]*[A-Za-z0-9])?")
s.matches("[A-Za-z](?:\\w*[A-Za-z0-9])?")
Если строка может содержать разрывы строк, используйте
s.matches("(?s)[A-Za-z](?:[A-Za-z0-9_]*[A-Za-z0-9])?")
s.matches("(?s)[A-Za-z](?:\\w*[A-Za-z0-9])?")
, где (?s)
позволяет .
сопоставлять символы разрыва строки.