eval vs bash through tube

Вдохновленный комментариями mikeserv, я сейчас делаю это с помощью команды

node --version | cut -d. -f1 | cut -c2-

. Здесь используется cut с . разделитель для извлечения только строки v . Затем он снова использует команду cut, чтобы взять все символы, начиная со второго, что удаляет v .

Здесь используются только coreutils (кроме node ), что делает его максимально переносимым.

6
07.05.2018, 07:17
1 ответ

Краткий ответ

Команда, запускаемая eval, выполняется в текущей оболочке, а команда, переданная в bash, выполняется в подчиненной оболочке -, например.:

> echo 'x=42' | bash; echo $x

> eval 'x=42'; echo $x
42

Более длинный ответ

В комментариях утверждалось, что в более поздних версияхbash(>=4.2 )первая команда также могла иметь такой же эффект. Однако, похоже, это не так.

На самом деле есть пара факторов, из-за которых конвейерная команда не запускается в текущем сеансе :конвейера и команды bash.

По большей части конвейерные команды выполняются в подоболочках. Руководство Bash(Раздел 3.2.2 :Трубопроводы)говорит следующее:

Each command in a pipeline is executed in its own subshell (see Command Execution Environment).

Как указано в комментариях, это поведение можно изменить с помощью параметра lastpipe. Руководство Bash (, раздел 4.3.2 :Встроенная программа Shopt)говорит следующее об опции lastpipe:

lastpipe

If set, and job control is not active, the shell runs the last command of a pipeline not executed in the background in the current shell environment.

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

Первое включениеlastpipe:

> shopt -s lastpipe

Затем отключите управление заданием -:

> set +m

Теперь выполните команду, которая устанавливает переменную внутри канала:

> unset x
> echo x=42 | while IFS= read -r line; do eval "${line}"; done;
> echo $x
42

Обратите внимание, что мы используем цикл whileи команду readв качестве обходного -, так как команда evalне может считывать ввод со стандартного ввода (, следовательно, не может получать ввод из конвейера ).

Этот пример демонстрирует, что самая правая -команда в конвейере может фактически выполняться в текущей оболочке. Однако на самом деле это не влияет на наш исходный пример. Даже при включенном lastpipeи отключенном управлении заданием -мы все равно получаем следующий результат при передаче вbash:

> echo 'x=42' | bash; echo $x

>

Это связано с тем, что сама команда bashвыполняет ввод в подоболочке.

20
27.01.2020, 20:20

Теги

Похожие вопросы