Bash: указание переменных среды для эха в командной строке?

Рассмотрим этот fragment:

$ SOMEVAR=AAA $ echo zzz $SOMEVAR zzz zzz AAA zzz 

Здесь я установил $SOMEVAR в AAA в первой строке – и когда я повторяю его во второй строке, я получаю содержимое AAA как ожидалось.

Но тогда, если я попытаюсь указать переменную в той же командной строке, что и echo :

 $ SOMEVAR=BBB echo zzz $SOMEVAR zzz zzz AAA zzz 

… Я не получаю BBB как я ожидал, – я получаю старую ценность ( AAA ).

Так ли это должно быть? Если да, то как же тогда вы можете указать такие переменные, как LD_PRELOAD=/... program args ... и заставить его работать? Что мне не хватает?

6 Solutions collect form web for “Bash: указание переменных среды для эха в командной строке?”

То, что вы видите, – это ожидаемое поведение. Проблема в том, что родительская shell оценивает $SOMEVAR в командной строке до того, как она вызывает команду с измененной средой. Вы должны получить оценку $SOMEVAR отложенной до тех пор, пока не будет установлена ​​среда.

Ваши ближайшие варианты include:

  1. SOMEVAR=BBB eval echo zzz '$SOMEVAR' zzz .
  2. SOMEVAR=BBB sh -c 'echo zzz $SOMEVAR zzz' .

Оба они используют одинарные кавычки, чтобы предотвратить вычисление родительской оболочки $SOMEVAR ; он оценивается только после того, как он установлен в среде (временно, на протяжении одной команды).

Другой вариант – использовать обозначение суб-оболочки (как также было предложено Маркусом Кеном в его ответе ):

 (SOMEVAR=BBB; echo zzz $SOMEVAR zzz) 

Переменная задается только в под-оболочке

Проблема, пересмотренная

Совершенно откровенно, руководство смущает по этому вопросу. В руководстве GNU Bash говорится:

Среда для любой простой команды или функции [обратите внимание, что это исключает встроенные функции] может быть временно добавлена, предварительно назначив ей назначения параметров, как описано в параметрах Shell. Эти утверждения присваивания влияют только на среду, видимую этой командой.

Если вы действительно разбираете предложение, то это говорит о том, что среда для команды / функции изменена, но не среда для родительского процесса. Итак, это сработает:

 $ TESTVAR=bbb env | fgrep TESTVAR TESTVAR=bbb 

потому что среда для команды env была изменена до ее выполнения. Однако это не сработает:

 $ set -x; TESTVAR=bbb echo aaa $TESTVAR ccc + TESTVAR=bbb + echo aaa ccc aaa ccc 

из-за того, что расширение параметра выполняется оболочкой.

Шаги переводчика

Другая часть проблемы заключается в том, что Bash определяет эти шаги для своего интерпретатора:

  1. Считывает свой вход из файла (см. Раздел «Сценарии оболочки») из строки, предоставленной в качестве аргумента для опции -c invocation (см. «Вызов Bash») или из терминала пользователя.
  2. Прерывает ввод в слова и операторы, подчиняясь правилам цитирования, описанным в Quoting. Эти маркеры разделяются метасимволами. На этом этапе выполняется расширение псевдонима (см. Псевдонимы).
  3. Разбирает токены в простые и составные команды (см. Команды оболочки).
  4. Выполняет различные расширения оболочки (см. Раздел «Расширения оболочки»), разбивая расширенные токены на списки имен файлов (см. «Расширение имен файлов»), а также команды и аргументы.
  5. Выполняет любые необходимые перенаправления (см. «Перенаправления») и удаляет операторы перенаправления и их операнды из списка аргументов.
  6. Выполняет команду (см. Выполнение команд).
  7. Необязательно ожидает завершения команды и сбора ее статуса выхода (см. «Статус выхода»).

Что здесь происходит, так это то, что встроенные функции не имеют собственной среды выполнения, поэтому они никогда не видят измененную среду. Кроме того, простые команды (например, / bin / echo) действительно получают модифицированную ennvironment (поэтому работал пример env), но расширение оболочки происходит в текущей среде на шаге 4.

Другими словами, вы не передаете ‘aaa $ TESTVAR ccc’ в / bin / echo; вы передаете интерполированную строку (как расширенную в текущей среде) в / bin / echo. В этом случае, поскольку в текущей среде нет TESTVAR , вы просто передаете команду «aaa ccc».

Резюме

Документация может быть намного понятнее. Хорошо, что есть переполнение стека!

Смотрите также

http://www.gnu.org/software/bash/manual/bashref.html#Command-Execution-Environment

Чтобы достичь желаемого, используйте

 ( SOMEVAR=BBB; echo zzz $SOMEVAR zzz ) 

Причина:

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

  • Вам нужно сделать назначение внутри среды подсетей , чтобы убедиться, что оно не сохраняется за пределами текущей строки.

Это решение более короткое, более аккуратное и более эффективное, чем некоторые другие, в частности, оно не создает новый процесс.

Причина в том, что это устанавливает переменную среды для одной строки. Но, echo не делает расширения, bash . Следовательно, ваша переменная фактически расширяется до выполнения команды, хотя SOME_VAR является BBB в контексте команды echo.

Чтобы увидеть эффект, вы можете сделать что-то вроде:

 $ SOME_VAR=BBB bash -c 'echo $SOME_VAR' BBB 

Здесь переменная не разворачивается до тех пор, пока не завершится дочерний процесс, поэтому вы увидите обновленное значение. если вы снова проверите SOME_VARIABLE в родительской оболочке, это все равно AAA , как и ожидалось.

 SOMEVAR=BBB; echo zzz $SOMEVAR zzz 

Использовать ; для разделения операторов, находящихся в одной строке.

Вот одна из альтернатив:

 SOMEVAR=BBB && echo zzz $SOMEVAR zzz 
  • Переменная окружения Deleted Path, как восстановить?
  • Команда javac не найдена
  • Неверная передача java-сообщений
  • Создайте новое окно терминала (Mac OS X)?
  • Microsoft Word внезапно не сохранит файлы; «Слово не может создать рабочий файл - проверьте переменную среды temp»
  • Передача переменной среды через SSH / цитирование в bash / sh / csh / tcsh
  • Каково точное значение IFS = $ '\ n'?
  • Каковы специальные переменные оболочки доллара?
  • Переопределение HOMEDRIVE и HOMEPATH в качестве пользователя Windows 7
  • Как настроить пользовательские переменные среды (например, PATH) из учетной записи не администратора для Windows 7
  • Настройка переменной среды JAVA_HOME
  • Interesting Posts

    Как перемещать текст по изображению

    Добавление строк в файл с помощью StreamWriter

    Как передать дополнительный параметр с помощью страницы входа в систему безопасности весны

    Как рассчитать разницу во времени в сценарии bash?

    Как реализовать перечисление с дженериками?

    Word 2010: Как ссылаться на пользовательские свойства документа?

    Как заставить Thunderbird загружать все электронные письма с помощью IMAP?

    Тип Interop не может быть встроен

    У .NET есть способ проверить, содержит ли List a все элементы в списке b?

    Как сделать макет с закругленными углами ..?

    Определите, используется ли приложение Android в первый раз

    Является ли выражение / start /, / end / range когда-либо полезным в awk?

    moveCamera с ошибками CameraUpdateFactory.newLatLngBounds

    System.Diagnostics.Process.Start не работает с IIS

    Конструкция JTable для синхронизации с внутренней структурой данных

    Давайте будем гением компьютера.