O * significa zero ou mais correspondências e corresponde o mais rápido possível. Se você executar esse comando sem o sinalizador g (o que significa que sed será interrompido após a primeira substituição), você obterá como saída habc 123 . Isso ocorre porque ele começa a ler da esquerda para a direita e, como não conseguiu corresponder a a , ele simplesmente coincide com o início da linha e, em seguida, para lá.
Usando o sinalizador global ( g ), ele continuará tentando corresponder ao restante da string e, como * corresponde à string vazia quando não pode corresponder a nada, ela colocará h toda vez que não pode corresponder a mais números.
Observe que sua segunda tentativa é equivalente a sed "s/[0-9]\+/h/" . Aqui + significa uma ou mais correspondências, o que significa que não corresponderá à string vazia quando não encontrar um número para substituir.