Почему установка переменной перед командой legal в bash?

Я только что столкнулся с несколькими ответами, например, для разбора текстового файла с разделителями …, которые используют конструкцию:

while IFS=, read xx yy zz;do echo $xx $yy $zz done < input_file 

где переменная IFS задается перед командой read .

Я читал ссылку на bash, но не могу понять, почему это законно.

Я пытался

 $ x="once upon" y="a time" echo $x $y 

из командной строки bash, но ничего не получилось. Может ли кто-нибудь указать мне, где этот синтаксис определен в ссылке, который позволяет настроить IFS-переменную таким образом? Это особый случай, или я могу сделать что-то подобное с другими переменными?

5 Solutions collect form web for “Почему установка переменной перед командой legal в bash?”

Он находится под оболочкой Grammar, Simple Commands (выделено мной):

Простая команда представляет собой последовательность необязательных назначений переменных, за которыми следуют пробельные слова и перенаправления, и завершается оператором управления. Первое слово указывает команду, которая должна быть выполнена, и передается как аргумент нуль. Остальные слова передаются в качестве аргументов вызываемой команды.

Таким образом, вы можете передать любую переменную, которую хотите. Ваш пример echo не работает, потому что переменные передаются команде, а не в оболочке. Оболочка расширяет $x и $y перед вызовом команды. Это работает, например:

 $ x="once upon" y="a time" bash -c 'echo $x $y' once upon a time 

Определенные переменные становятся как переменные среды для разветвленного процесса.

Если вы запустите

 A="b" echo $A 

то bash сначала расширяет $A до "" а затем запускает

 A="b" echo 

Вот правильный способ:

 x="once upon" y="a time" bash -c 'echo $x $y' 

Обратите внимание на одинарные кавычки в bash -c , иначе у вас будет такая же проблема, как указано выше.

Таким образом, ваш пример цикла является законным, потому что команда bash builtin 'read' будет искать IFS в своих переменных окружения и найти. Следовательно,

 for i in `TEST=test bash -c 'echo $TEST'` do echo "TEST is $TEST and I is $i" done 

будет печатать TEST is and I is test

Наконец, что касается синтаксиса, в цикле for ожидается строка. Поэтому мне пришлось использовать backticks, чтобы сделать его командой. Однако, в то время как циклы ожидают командный синтаксис, например IFS=, read xx yy zz .

Команда, которую вы предоставляете, отличается от того, что $x и $y разворачиваются до echo команды echo , поэтому используются их значения в текущей оболочке, а не значения, которые echo увидит в своей среде, если они будут выглядеть.

man bash

ОКРУЖАЮЩАЯ СРЕДА

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

Переменные расширяются до назначения переменной. По той очевидной причине, что var=x будет работать и другим способом, но var=$othervar не будет. Т.е. ваш $x нужен, прежде чем он будет доступен. Но это не главная проблема. Основная проблема заключается в том, что командную строку можно изменить только оболочкой, но присваивание не станет частью среды оболочки.

Вы смешиваетесь с функциями: вам нужна замена командной строки, но поместите определение переменной в среду команд. Оболочка командной строки должна выполняться оболочкой. Среда должна быть явно использована вызываемой командой. Независимо от того, как это делается, зависит от команды.

Преимущество этого использования заключается в том, что вы можете настроить среду для подпроцесса, не затрагивая среду оболочки.

 x="once upon" y="a time" bash -c 'echo $x $y' 

работает так, как вы ожидаете, потому что в этом случае обе функции объединены: замена командной строки не выполняется вызывающей оболочкой, а оболочкой подпроцесса.

Я собираюсь сделать более общую картину « почему это законно»,

Ответ. Чтобы вы могли вызвать или вызвать программу, и для этого вызова используйте только переменную с определенной переменной.

В качестве примера: у вас есть параметр для подключения к базе данных под названием «db_connection», и обычно вы передаете «test» в качестве имени для подключения тестовой базы данных. Фактически вы можете даже установить его как значение по умолчанию, которое вам тогда не нужно передавать явно. Иногда, однако, вы хотите работать с базой данных ci. Таким образом, вы передаете параметр как «ci», а затем вызываемая программа использует этот параметр базы данных как имя db для использования для всех вызовов базы данных. Для следующего прогона, если вы не повторите этот подход и просто вызовите программу, переменная вернется к своему предыдущему значению по умолчанию.

  • В чем разница между env, setenv, export и когда использовать?
  • Связь между процессами запуска оболочки и средой родительского процесса
  • Почему некоторые скрипты используют экспорт для системных переменных?
  • Как печатать переменные и значения оболочки для их копирования и вставки?
  • Можно ли изменить оболочку, используемую для запуска приложений GUI из диспетчера рабочего стола?
  • Какие сценарии bash выполняются при запуске терминала?
  • Почему echo $ SHELL всегда показывает / bin / bash?
  • Выдать ошибку при использовании пустых переменных оболочки
  • Что делает `env COLUMNS =% S ps ...` do?
  • Последняя неудачная команда в bash
  • Есть ли вред в использовании переменных, которые не установлены?
  • Linux и Unix - лучшая ОС в мире.