^(?!_) # don't start with _
(?!.*?_$) # don't end with _
[a-zA-Z] # the first character must be a letter
[a-zA-Z0-9_]+$ # after that digits and underscores are ok
Você expressou de duas maneiras diferentes que o primeiro caractere não deve ser _ , mas nada aqui diz nada sobre __ no meio.
Usando uma visão negativa, é simples expressar "um ou mais caracteres alfanuméricos ou _ , não comece com _ ou um dígito, não termine com _ e não permita __ anywhwere ”:
^(?![0-9_]|.*__.*_$|)[0-9A-Z_a-z]+$
Sem lookahead negativo (por exemplo, em awk ou grep -E ), você pode dividir as partes:
^[A-Za-z][0-9A-Za-z]*(_[0-9A-Za-z]+)*$
Comece com uma letra, depois zero ou mais alfanuméricos, então você pode ter sublinhados, mas cada um deve ser seguido por um ou mais alfanuméricos.