Я подозреваю, что это часть последовательности, которая ловит вас:
Слова, которые не являются переменными назначениями или перенаправлениями, раскрываются (см. Расширения оболочки). Если после раскрытия остаются какие-либо слова, первое слово считается именем команды, а остальные слова - аргументами.
Это из справочного руководства по Bash в разделе «Простое расширение команд».
В этом cmd=bashпримере переменные окружения не установлены, и bash обрабатывает командную строку через расширение параметра, оставляя bash -c "echo hi".
В этом prefix=hello=hiпримере снова нет присвоений переменных на первом проходе, поэтому обработка продолжается до раскрытия параметра, в результате чего появляется первое слово hello=hi.
Как только назначения переменных были обработаны, они не обрабатываются повторно во время выполнения команды.
Смотрите обработку и ее результаты в разделе 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
Для более безопасной вариации «переменное расширение», как «переменные окружения» eval, рассмотрим предложение wjandreaenv :
prefix=hello=hi
env "$prefix" bash -c 'echo "$hello"'
hi
Это не строго присваивание переменной командной строки, так как мы используем envосновную функцию утилиты для присвоения переменных среды команде, но она выполняет ту же цель. $prefixПеременный расширяются во время обработки командной строки, обеспечивая имя = значение env, который передает его вместе с bash.
envВместо этого вы можете использоватьeval, который IIRC является более безопасным, но медленнее.