Установка переменной окружения перед командой в Bash не работает для второй команды в пайпе
Описание проблемы
В определенной оболочке я обычно устанавливаю переменные и затем выполняю команду. Недавно я узнал о концепции добавления определения переменной перед командой:
FOO=bar somecommand someargs
Это работает... в целом. Однако, это не работает, когда вы пытаетесь изменить переменную типа LC_*, которая влияет на команду, но не на её аргументы (например, диапазоны символов [a-z]), или когда вы направляете вывод одной команды в другую:
FOO=bar somecommand someargs | somecommand2 # somecommand2 не знает о FOO
Я могу также добавить FOO=bar перед somecommand2, и это будет работать, но появляется нежелательное дублирование, и это не помогает с аргументами, которые интерпретируются в зависимости от переменной (например, [a-z]).
Какой хороший способ сделать это в одну строку?
Я думал о варианте вроде:
FOO=bar (somecommand someargs | somecommand2) # Это не работает
Я получил много хороших ответов! Цель состоит в том, чтобы сохранить это в одной строке, предпочтительно без использования export. Метод с вызовом Bash оказался в целом лучшим, хотя вариант с подстановкой и export был немного компактнее. Метод использования перенаправления вместо конвейера также интересен.
5 ответ(ов)
В данном примере, переменная окружения FOO устанавливается в значение bar для выполнения команды bash -c. Команда, заключенная в одинарные кавычки, это somecommand someargs | somecommand2. Это означает, что сначала выполняется somecommand с аргументами someargs, а затем результат этого выполнения передается на вход команде somecommand2 с помощью конвейера (pipeline).
Таким образом, FOO будет доступна только в рамках этой команды и не повлияет на другие процессы. Если вы хотите использовать FOO только в рамках выполнения данной команды, то такой способ является правильным.
Если у вас есть дополнительные вопросы или требуется больше деталей, пожалуйста, уточните!
Используйте команду env.
Например, можно выполнить так: env FOO=BAR команда. Обратите внимание, что переменные окружения будут восстановлены/остановлены в своем первоначальном состоянии после завершения работы команды.
Однако будьте осторожны с заменой переменных оболочки. Например, если вы хотите явно сослаться на $FOO в той же строке команды, вам, возможно, потребуется экранировать его, чтобы ваша интерпретируемая оболочка не выполнила замену до запуска env.
$ export FOO=BAR
$ env FOO=FUBAR bash -c 'echo $FOO'
FUBAR
$ echo $FOO
BAR
Вы также можете использовать eval:
FOO=bar eval 'somecommand someargs | somecommand2'
Поскольку этот ответ с использованием eval не всем кажется приемлемым, позвольте мне прояснить один момент: когда используется указанный синтаксис — с одинарными кавычками, это абсолютно безопасно. Так как данный подход не запускает внешние процессы (в отличие от принятого ответа) и не выполняет команды в дополнительной подсистеме (как в другом ответе).
Поскольку мы получаем несколько стандартных просмотров, было бы неплохо предложить альтернативу eval, которая устроит всех и имеет все преимущества (а, возможно, даже больше!) этого быстрого "трика" с eval. Просто используйте функцию! Определите функцию со всеми вашими командами:
mypipe() {
somecommand someargs | somecommand2
}
И выполните её с вашими переменными окружения следующим образом:
FOO=bar mypipe
Простой подход заключается в использовании ;.
Например:
ENV=prod; ansible-playbook -i inventories/$ENV --extra-vars "env=$ENV" deauthorize_users.yml --check
command1; command2 выполняет command2 после выполнения command1, последовательно. Не имеет значения, были ли команды успешными или нет.
Оба приведенных варианта работают одинаково.
Первый вариант:
some_var="some_value" && echo "${some_var}"
использует оператор &&, который выполняет команду справа (в данном случае echo "${some_var}") только в том случае, если команда слева завершилась успешно. В данном случае, поскольку присваивание переменной всегда успешно, echo будет выполнен, и выведет значение переменной.
Второй вариант:
some_var="some_value"; echo "${some_var}"
просто отделяет две команды точкой с запятой. Здесь обе команды выполняются последовательно, и переменная также будет выведена.
Таким образом, оба метода корректны и дают одинаковый результат. Вы можете использовать любой из них в зависимости от ваших предпочтений или контекста, в котором они используются.
Установить переменные окружения из файла с парами ключ/значение
Как изменить цвет вывода echo в Linux
Как работает "cat << EOF" в bash?
Как разделить большой текстовый файл на меньшие файлы с равным количеством строк?
Автоматический вход в Docker через Bash-скрипт