Кавычки в сценариях оболочки не ведут себя иначе, чем кавычки в командах оболочки.
С синтаксисом $(gpg -d filename.gpg)
вы выполняете не сценарий оболочки, а обычную отдельную команду.
Что делает ваша команда
- Выполняется
gpg -d filename.gpg
- Из результата в качестве команды для выполнения берется первое (отделенное IFS) слово
- Он принимает каждые другие (разделенные IFS) слова, включая слова из дополнительных строк, в качестве параметров
- Выполняет команду
Из следующих практических примеров вы можете увидеть, чем он отличается от выполнения сценария оболочки:
- Удалите слово export из filename.gpg: тогда команда будет
SOME_ENV_VAR='123'
, которая не понимается как присвоение переменной (вы получите SOME_ENV_VAR='123': command not found
).
- Если вы добавите несколько строк, они будут восприниматься не как отдельные командные строки, а как параметры самой первой команды (
export
).
- Если вы измените
export SOME_ENV_VAR='123'
на export SOME_ENV_VAR=$PWD
, SOME_ENV_VAR будет содержать не содержимое переменной PWD, а строку $var
Почему это так?
См. , как bash выполняет расширение при анализе команды.
Есть много шагов. $(...)
называется «подстановка команд» и является четвертым этапом. Когда это будет сделано, ни один из предыдущих шагов не будет выполнен снова. Это объясняет, почему ваша команда не работает, когда вы удаляете слово export
, и почему переменные не подставляются в результат.
Более того, «удаление цитаты» является последним шагом, а руководство гласит :
все вхождения без кавычек символов ‘\’, ‘'’ и ‘" ’
Не в результате одного из вышеперечисленных расширений удалены
Поскольку одинарные кавычки были результатом расширения «подстановка команд», они не были удалены Вот почему содержимое SOME_ENV_VAR составляет '123'
, а не 123
.
Почему eval
работает?
Потому что eval запускает еще один полный анализ своих параметров. Весь набор расширений запускается снова.
Из руководства :
Аргументы объединяются в одну команду, которая затем читается и выполняется
Обратите внимание, что это означает, что вы все еще запускаете одну отдельную команду, а не сценарий оболочки. Если ваш filename.gpg
скрипт имеет несколько строк, последующие строки будут добавлены в список аргументов первой (и единственной) команды.
Что мне тогда делать?
Просто используйте source
вместе с процессом замены .
source <(gpg -d filename.gpg)
В отличие от eval
, source
используется для выполнения сценария оболочки в текущем контексте. Подстановка процесса предоставляет псевдо-имя файла, которое содержит результат подстановки (то есть вывод gpg
).