Левая сторона трубы это подоболочка? - PullRequest
11 голосов
/ 23 апреля 2011

Edit:

Мой комментарий ниже относительно sed 's@^@ @' <(f1) неверен В то время как $BASH_SUBSHELL указывает, что мы находимся на том же уровне, что и запуск, переменные теряются в основном скрипте. основываясь на ответе Гордона, я протестировал f1 > >(sed 's@^@ @'), и это, кажется, работает правильно. Тем не менее, BASH_SUBSHELL не должен быть 1, а не 0 для первой формы?


Рассмотрим этот маленький тест

#!/bin/bash
declare -i i=0
function f1()
{
  let i++
  echo "In f1, SUBSHELL: $BASH_SUBSHELL, i=$i" >&2
}

f1
f1 | sed 's@^@     @'

echo "at end, i=$i"

со следующим выводом:

In f1, SUBSHELL: 0, i=1
In f1, SUBSHELL: 1, i=2
at end, i=1

(цель sed - просто иметь канал к чему-то, не ожидайте, что он что-то сделает, потому что f1 выводит в stderr)

Функция f1 записывает текущий BASH_SUBSHELL и текущее значение i

Я знаю, почему в конце скрипта мы получаем i=1, потому что второй вызов был в подоболочке, а значение i в подоболочке 1 было потеряно.

Чего я не знаю, так это того, почему левая сторона трубы не была выполнена в текущей оболочке

Хотя я подумал, что смогу избежать этого с sed 's@^@ @' <(f1) Я хотел бы знать, почему левая сторона не находится на том же уровне, что и основной скрипт

Ответы [ 2 ]

17 голосов
/ 23 апреля 2011

со страницы руководства bash : «Каждая команда в конвейере выполняется как отдельный процесс (т. Е. В подоболочке)». Я предполагаю, что было бы возможно выполнить один компонент конвейера в текущей оболочке (то есть первый или последний, или, может быть, один в середине), он не воспроизводит избранное следующим образом: они все Выполнить в подоболочках. Если вы измените свой скрипт следующим образом:

#!/bin/bash
declare -i i=0
function f1()
{
    let i++
    echo "In f1, SUBSHELL: $BASH_SUBSHELL, i=$i" >&2
}

f1
f1 | f1 | f1

echo "at end, i=$i"

печатает:

In f1, SUBSHELL: 0, i=1
In f1, SUBSHELL: 1, i=2
In f1, SUBSHELL: 1, i=2
In f1, SUBSHELL: 1, i=2
at end, i=1

, потому что все 3 вызова f1 в конвейере выполняются в подоболочках.

0 голосов
/ 27 февраля 2014

Вот очень краткий пример, если кому-то все равно:

cd / && cd /tmp/ | pwd  ; pwd
/
/

Или:

cd / && cd /tmp/ | cd /var/  ; pwd
/

Да, на этой странице все сказано

http://linux.die.net/man/1/bash# Каждая команда в конвейере выполняется как отдельный процесс (т. Е. В подоболочке).

...