Вчера мне было предложено, что использование подстановки команд в bash приводит к возникновению ненужной подоболочки. Совет был специально для этого варианта использования:
# Extra subshell spawned
foo=$(command; echo $?)
# No extra subshell
command
foo=$?
Насколько я могу понять, это кажется правильным для этого варианта использования. Тем не менее, быстрый поиск, пытаясь проверить это, приводит к путанице запутывающих и противоречивых советов. Кажется, популярная мудрость говорит, что ВСЕ использование подстановки команд порождает подоболочку. Например:
Подстановка команд расширяется до вывода команд. Эти команды выполняются в подоболочке, а их данные stdout - это то, к чему расширяется синтаксис подстановки. (источник)
Это кажется достаточно простым, если вы не продолжаете копать, и в этом случае вы начнете находить ссылки на предложения, что это не так.
Подстановка команды необязательно вызывает подселочку, и в большинстве случаев это не будет. Единственное, что он гарантирует, это оценка вне порядка: она просто сначала вычисляет выражения внутри подстановки, а затем оценивает окружающий оператор, используя результаты подстановки. (источник)
Это кажется разумным, но верно ли это? Этот ответ на вопрос, связанный с подоболочкой, подсказывал мне, что man bash
имеет в виду следующее:
Каждая команда в конвейере выполняется как отдельный процесс (т.е. в подоболочке).
Это подводит меня к основному вопросу. Что именно приведет к подстановке команд, чтобы породить подоболочку, которая не была бы порождена в любом случае для выполнения одних и тех же команд в отдельности?
Пожалуйста, рассмотрите следующие случаи и объясните, какие из них несут накладные расходы дополнительной подоболочки:
# Case #1
command1
var=$(command1)
# Case #2
command1 | command2
var=$(command1 | command2)
# Case #3
command1 | command 2 ; var=$?
var=$(command1 | command2 ; echo $?)
Выполняет ли каждая из этих пар одинаковое количество подоболочек? Есть ли разница в реализациях POSIX и bash? Существуют ли другие случаи, когда использование подстановки команд создавало бы подоболочку, в которой выполнение одного и того же набора команд в отдельности не было бы?