Почему этот код не работает? - PullRequest
2 голосов
/ 16 февраля 2012
x="a=b"
`echo $x`
echo $a

Я ожидаю, что вторая строка сгенерирует "a = b" и выполнит ее в контексте основной оболочки, что приведет к новой переменной a со значением b. Однако, что я действительно получаю (если я ввожу команды вручную), так это сообщение об ошибке после второй строки, bash: a=b: command not found

Почему это так?

Ответы [ 4 ]

4 голосов
/ 16 февраля 2012

Попробуйте

eval $x

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

3 голосов
/ 16 февраля 2012

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

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

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

$(echo ls)

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

1 голос
/ 16 февраля 2012

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

0 голосов
/ 16 февраля 2012

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

...