Почему этот код не работает?
x="a=b"
`echo $x`
echo $a
Я ожидаю, что вторая строка сгенерирует "a=b" и выполнит ее в контексте основной оболочки, что приведет к новой переменной a
со значением b
, Тем не менее, что я действительно получаю (если я ввожу команды вручную), это сообщение об ошибке после второй строки, bash: a=b: command not found
Почему это так?
4 ответа
Это из-за порядка, в котором bash анализирует командную строку. Он ищет определения переменных (например, a=b
) перед выполнением подстановки переменных и команд (например, команды в обратных галочках). Из-за этого к тому времени echo $x
заменяется a=b
, слишком поздно, чтобы bash увидел это как определение переменной, и вместо этого он анализируется как команда. То же самое произошло бы, если бы вы просто использовали $x
в качестве команды (вместо эха в кавычках). Как и в ответе @ 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
, и это устраняет, по крайней мере, часть потенциальных проблем.
То, что делает ваша первая строка эха, выполняется в подоболочке и возвращает ее значение вызываемой стороне. Тот же результат достигается с помощью $()
и - между прочим - проще в использовании, чем кавычки.
Итак, то, что вы делаете, это первый запуск echo $x
(который возвращает a=b
). И, из-за кавычек, a=b
возвращается в оболочку, которая пытается запустить эту строку в качестве команды, которая, очевидно, не будет работать.
Попробуйте это в оболочке:
$(echo ls)
И вы четко увидите, что происходит.
Ты пробовал $x
в этих смешных апострофах? Без echo
Эхо, кажется, только для отображения строки, а не выполнения команд.