Это из-за порядка, в котором bash анализирует командную строку.Он ищет определения переменных (например, a=b
) перед тем, как выполнит подстановку переменных и команд (например, команды в обратных галочках).Из-за этого, к тому времени, когда echo $x
заменяется на a=b
, bash уже слишком поздно, чтобы увидеть это как определение переменной, и вместо этого он анализируется как команда.То же самое произошло бы, если бы вы просто использовали $x
в качестве команды (вместо echo в обратных галочках).Как и в ответе @ mvds, команду eval
можно использовать для принудительного повторного анализа команды с начала, что означает, что она будет распознана как определение переменной:
$ x="a=b"
$ `echo $x`
-bash: a=b: command not found
$ $(echo $x) # Exact same thing, but with cleaner syntax
-bash: a=b: command not found
$ $x # This also does the same thing, but without some extra steps
-bash: a=b: command not found
$ eval "$x" # This will actually work
$ echo $a
b
$ a= # Start over
$ eval "$(echo "$x")" # Another way of doing the same thing, with extra steps
$ echo $a
b
Обратите внимание, что при использованииeval
Я поместил все ссылки на $x
в двойных кавычках - чтобы предотвратить последующие фазы синтаксического анализа bash (например, разбиение слов) дважды , так как bash завершитсяего обычный процесс синтаксического анализа, затем распознайте команду eval
, а затем повторите весь процесс синтаксического анализа снова .С помощью eval
действительно легко получить неожиданные результаты, и это устраняет, по крайней мере, часть потенциальных проблем.