В комментарии к другому сообщению @JonathanLeffler заявил, что:
{...} | somecommand запускается в под-оболочке и не влияет на родительскую оболочку. Демо-версия:
X=PQR; echo $X; { X=ABC; echo $X; } | cat; echo $X
(с выводом PQR, ABC, PQR на три строки)
и действительно:
[email protected]:tmp$X=PQR; echo $X; { X=ABC; echo $X; } | cat; echo $X
PQR
ABC
PQR
Однако man bash
говорит, что {.. }
не выполняется в подоболочке:
{ list; }
list is simply executed in the current shell environment. list must be
terminated with a newline or semicolon. This is known as a group command.
Так что здесь происходит? Неужели man bash
не прав? Я знаю, что каждая часть конвейера выполняется в подоболочке; но я не вижу, как это вызывает наблюдаемое поведение. Например:
[email protected]:tmp$X=PQR; echo $X | sed; X=ABC; echo $X | sed; echo $X
PQR
ABC
ABC
Отредактировано, чтобы добавить:
Несколько человек предложили использовать echo $$
чтобы показать, что вещи являются (или не являются) частями подоболочки. Это совсем не полезно, так как $$
раскрывается на этапе расширения параметров, который происходит задолго до того, как будут выполнены какие-либо команды.
В качестве примера:
[email protected]:tmp$echo 1$$; ps; ( echo 2$$; ps ); echo 3$$; ps
11194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
21194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
7894 ttys000 0:00.00 -bash
31194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
[email protected]:tmp$
Вы можете видеть, что второй вызов ps
произошел внутри подоболочки с pid 7894
; но echo 2$$
прежнему показывает значение, которое bash подставил на этапе расширения переменной, до того, как он породил подоболочку
Для контраста и демонстрации того, что {.. }
не порождает подоболочку:
[email protected]:tmp$echo 1$$; ps; { echo 2$$; ps; }; echo 3$$; ps
11194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
21194
PID TTY TIME CMD
1194 ttys000 0:00.22 -bash
31194
PID TTY TIME CMD
1194 ttys000 0:00.23 -bash
Просто чтобы доказать, что @nos верен, добавьте конвейер к приведенному выше:
[email protected]ious-wired:tmp$echo 1$$; ps; { echo 2$$; ps; } | sed ; echo 3$$; ps
11194
PID TTY TIME CMD
1194 ttys000 0:00.25 -bash
21194
PID TTY TIME CMD
1194 ttys000 0:00.25 -bash
7945 ttys000 0:00.00 -bash
7946 ttys000 0:00.00 sed
31194
PID TTY TIME CMD
1194 ttys000 0:00.25 -bash
Как и ожидалось, оболочка порождает две подоболочки, по одной на каждую сторону трубопровода.