Eu suspeito que esta é a parte da sequência que está pegando você:
As palavras que não são atribuições ou redirecionamentos de variáveis são expandidas (consulte Expansões do Shell). Se alguma palavra permanecer após a expansão, a primeira palavra será o nome do comando e as palavras restantes serão os argumentos
Isso é do manual de referência do Bash na seção Expansão de comando simples.
No cmd=bashexemplo, nenhuma variável de ambiente é definida e o bash processa a linha de comandos através da expansão de parâmetros, saindo bash -c "echo hi".
No prefix=hello=hiexemplo, novamente não há atribuições de variáveis na primeira passagem; portanto, o processamento continua com a expansão de parâmetros, resultando na primeira palavra de hello=hi.
Depois que as atribuições de variáveis são processadas, elas não são processadas novamente durante a execução do comando.
Veja o processamento e seus resultados em set -x:
$ prefix=hello=hi
+ prefix=hello=hi
$ $prefix bash -c 'echo $hello'
+ hello=hi bash -c 'echo $hello'
-bash: hello=hi: command not found
$ hello=42 bash -c 'echo $hello'
+ hello=42
+ bash -c 'echo $hello'
42
Para uma variação mais segura de "expansão variável" -com- "variáveis de ambiente" que eval, considere a sugestão de wjandrea deenv :
prefix=hello=hi
env "$prefix" bash -c 'echo "$hello"'
hi
Não é estritamente uma atribuição de variável da linha de comando, já que estamos usando a envfunção principal do utilitário de atribuir variáveis de ambiente a um comando, mas cumpre o mesmo objetivo. A $prefixvariável é expandida durante o processamento da linha de comandos, fornecendo o nome = valor para envquem o transmite bash.
envvez deeval, qual IIRC é mais seguro, mas mais lento.