Почему этот код не работает?

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, и это устраняет, по крайней мере, часть потенциальных проблем.

Пытаться

eval $x

(И нам нужно 30 символов для ответа)

То, что делает ваша первая строка эха, выполняется в подоболочке и возвращает ее значение вызываемой стороне. Тот же результат достигается с помощью $() и - между прочим - проще в использовании, чем кавычки.

Итак, то, что вы делаете, это первый запуск echo $x (который возвращает a=b). И, из-за кавычек, a=b возвращается в оболочку, которая пытается запустить эту строку в качестве команды, которая, очевидно, не будет работать.

Попробуйте это в оболочке:

$(echo ls)

И вы четко увидите, что происходит.

Ты пробовал $x в этих смешных апострофах? Без echoЭхо, кажется, только для отображения строки, а не выполнения команд.

Другие вопросы по тегам